def decorator_with_args(decorator):
def new(*args, **kwargs):
def new2(fn):
return decorator(fn, *args, **kwargs)
return new2
return new
@decorator_with_args
def typecheck(fn, *decorator_args):
def new(*args):
if len(decorator_args) != len(args):
raise Exception('Wrong number of arguments given to\
decorator.')
for x in range(0, len(args)):
if type(args[x]) != decorator_args[x]:
raise TypeError('Argument %i is of wrong type.\
%s expected, %s received.'%\
(x+1, str(decorator_args[x]),
str(type(args[x]))))
return fn(*args)
return new
The reason that two decorators are created in the above code is, that the typecheck decorator is decorated by the decorator_with_args decorator to enable the decorator to take arguments - which is not otherwise possible.
Using the typecheck decorator is as simple as:
@typecheck(int, int)
def add(x, y):
return x+y
Now, whenever the add function is called, it will be checked whether the arguments x and y are indeed integers, and if not a TypeError exception will be thrown.
Feel free to copy the code into your own projects - consider it released under a BSD licence :-)