【问题标题】:Decorator and closures装饰器和闭包
【发布时间】:2012-12-25 22:58:07
【问题描述】:

我正在通过How to make a chain of function decorators? 了解装饰器。

在下面的示例中,我们看到“method_to_decorate”由于闭包而可以被包装函数访问。 但是,我不明白包装函数如何访问参数 selflie

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?

【问题讨论】:

    标签: python closures decorator python-decorators


    【解决方案1】:

    返回的wrapper 替换了修饰函数,因此被视为方法。原来的sayYourAge 采用了(self, lie),新的wrapper 也是如此。

    所以,当调用l.sayYouAge(-3) 时,您实际上是在调用嵌套函数wrapper,那时它是一个绑定方法。绑定方法得到self 传入,-3 被分配给参数liewrapper 调用 method_to_decorate(self, lie),将这些参数传递给原始修饰函数。

    注意selflie 被硬编码到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
    

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

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

    【讨论】:

    • 谢谢.. 我们将“sayYourAge”方法显式发送给装饰器,而不是“self and lie”。它是如何通过的?
    • @rajpy:它在装饰器中是硬编码的。它根本没有被发送。装饰器不是通用的。
    • +1 你也可以(如果这对 OP 来说已经不算多的话),提到通常习惯的functool.wraps,嗯...decorate decorators ;)
    • @Tadeck:一次一步:-)
    • @Martijn Pieters:感谢您的详细解释。现在明白了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    • 2021-05-20
    • 2016-04-20
    • 2017-01-04
    • 2018-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多