I am going through the How to make a chain of function decorators?
to understand decorator.
In the following example, we see that “method_to_decorate” is accessible to wrapper function because of closures.
But, I didn’t understand how arguments self and lie are accessible to the wrapper function.
def method_friendly_decorator(method_to_decorate):
def wrapper(self, lie):
lie = lie - 3 # very friendly, decrease age even more :-)
return method_to_decorate(self, lie)
return wrapper
class Lucy(object):
def __init__(self):
self.age = 32
@method_friendly_decorator
def sayYourAge(self, lie):
print "I am %s, what did you think?" % (self.age + lie)
l = Lucy()
l.sayYourAge(-3)
#outputs: I am 26, what did you think?
The returned
wrapperreplaces the decorated function, and is thus treated as a method. The originalsayYourAgetook(self, lie)and so does the newwrapper.So, when calling
l.sayYouAge(-3)you are really calling the nested functionwrapper, which is by that time a bound method. Bound methods getselfpassed in, and-3is assigned to the argumentlie.wrappercallsmethod_to_decorate(self, lie), passing these arguments on to the original decorated function.Note that
selfandlieare hardcoded into thewrapper()signature; it is tightly bound to the decorated function. These were not taken from the decorated function, the programmer who wrote the wrapper knew beforehand what arguments would be expected of the wrapped version. Note that the wrapper doesn’t have to match arguments with the decorated function at all.You could add arguments, for example:
Now you can make Lucy lie about her age in different ways: