我目前正在尝试修饰,我无法理解一件事。我有简单的装饰:
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
如何作为参数发送给decorate
? add_attr
只获得2个参数,而且它们都不是foo
。
答案 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解释装饰器比我在网络上看到的任何其他内容更好。