装饰和封闭

raj*_*jpy 0 python closures decorator python-decorators

我正在经历如何制作一系列功能装饰器? 了解装饰.

在下面的示例中,我们看到由于闭包,包装函数可以访问"method_to_decorate".但是,我不明白参数如何self以及lie包装函数是否可访问.

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?
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 5

返回wrapper替换了修饰函数,因此被视为方法.原来sayYourAge(self, lie)等做了新的wrapper.

因此,在调用时,l.sayYouAge(-3)您实际上正在调用嵌套函数wrapper,这是当时绑定的方法.绑定方法self传入,并-3分配给参数lie.wrapper调用method_to_decorate(self, lie),将这些参数传递给原始修饰函数.

请注意self并将lie其硬编码到wrapper()签名中; 它与装饰功能紧密相连.这些不是从装饰函数中获取的,编写包装器的程序员事先知道对包装版本的期望是什么.需要注意的是包装不具有与装饰的功能相匹配的参数都没有.

您可以添加参数,例如:

def method_friendly_decorator(method_to_decorate):
     def wrapper(self, lie, offset=-3):
         lie += offset # very friendly, adjust age even more!
         return method_to_decorate(self, lie)
     return wrapper
Run Code Online (Sandbox Code Playgroud)

现在你可以用不同的方式让露西对她的年龄撒谎:

l.sayYourAge(-1, offset=1)  # will say "I am 32, what did you think?"
Run Code Online (Sandbox Code Playgroud)