There are two types of decorators, those without arguments (e.g @mydecorator) and those with arguments (e.g. @mydecorator('foo', 'bar'). For the case with no arguments, the code for your decorator will look as follows:
import functools
def mydecorator(f):
"""A simple decorator."""
@functools.wraps(f)
def wrapper(*args, **kwargs):
print 'Before %s in wrapper' % f.__name__
result = f(*args, **kwargs)
print 'After %s in wrapper' % f.__name__
return result
return wrapper
@mydecorator
def myfunc():
print 'Inside myfunc'
In case you are curious, we don't technically need to use the @functools.wraps decorator in our decorator, but it performs some very useful things for us. Take a look at this post if you want to know why we 'need' it.
If you want to pass arguments to your decorator, then your code will need be something like this:
import functools
def mydecorator(arg1, arg2):
"""A simple decorator with arguments."""
def wrap(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
print 'Decorator arguments: %s, %s' % (arg1, arg2)
print 'Before %s in wrapper' % f.__name__
result = f(*args, **kwargs)
print 'After %s in wrapper' % f.__name__
return result
return wrapper
return wrap
@mydecorator('foo', 'bar')
def myfunc():
print 'Inside myfunc'
It is very important to note that the arguments passed to the decorator are only evaluated once, the first time that the function is encountered. This essentially means that you cannot change the parameters to your decorator at runtime and if arg1 was 'foo', then it will be 'foo' until your program terminates. If you can look at the code above and understand why that is at first glance, then that is admirable. If you are like the rest of us, check out the great explanation of decorators here.
No comments:
Post a Comment