Python - 装饰器调用内部函数?

时间:2017-03-10 19:01:38

标签: python decorator python-decorators

我目前正在尝试修饰,我无法理解一件事。我有简单的装饰:

def new_decorator(func):
    print "Calling new_decorator()"
    def wrap(arg):
        print "Calling wrap()"
        func(arg)
    return wrap  

@new_decorator
def foo(name):
    print name

跑完后我们得到:

'Calling decorate()' 

仅在致电foo之后:

>>> foo('Jon')
Calling wrap()
Jon

直到现在我理解了一切(我想)。 new_decorator(func)在开始时调用foo作为参数,它返回wrap。但是现在我尝试了带参数的装饰器:

def add_attr(varname, value):
    def decorate(func):
        print "Calling decorate()"
        setattr(func, varname, value)
        return func
    return decorate

@add_attr('var', 'New attribute')
def foo():
    print "Calling foo()"
    print foo.var

运行时(不调用foo()),它返回:

'Calling decorate()'

foo()之后:

>>> foo()
Calling foo()
New attribute

我无法理解的是,为什么这个"内在"在调用decorate之前,函数foo在开始时被称为?在第一个例子中,它不是。函数foo如何作为参数发送给decorateadd_attr只获得2个参数,而且它们都不是foo

1 个答案:

答案 0 :(得分:2)

对于接受参数的装饰器,通常需要3层嵌套。想象一下装饰者接受作为"装饰制造者"的参数。 调用时应该返回一个装饰器

要理解这一点,请考虑以下代码

@new_decorator
def foo(name):
    print name

真的只是语法糖:

def foo(name):
    print name

foo = new_decorator(foo)

所以,同样地,这个:

@add_attr('var', 'New attribute')
def foo():
    print "Calling foo()"
    print foo.var

与此相同:

def foo():
    print "Calling foo()"
    print foo.var

foo = add_attr('var', 'New attribute')(foo)

这应该指导您正确编写add_attr的方向。

如果您在尝试几次后仍然感到困惑,我会推荐您a famous answer from e-satis解释装饰器比我在网络上看到的任何其他内容更好。