【发布时间】:2018-08-16 21:20:29
【问题描述】:
我一直在试验装饰器,发现了一个有趣的不一致之处,希望你能帮助我解决它。
首先我有一个这样的装饰器:
>>> def name(n):
... def decorator(fun):
... fun.name = n
... return fun
... return decorator
我是这样使用它的:
>>> @name("my name jeff")
... def f():
... print f.name
因为装饰器返回了乐趣,我可以同时做这两个:
>>> f()
my name jeff
>>> f.name
'my name jeff'
这一切都很好,符合我的预期。现在来了奇怪的一点。我的新装饰器如下:
>>> def name(n):
... def decorator(fun):
... fun.name = n
... def wrapper():
... return fun()
... return wrapper
... return decorator
在我看来,这应该和之前的一样,但是我明白了:
>>> @name("my name jeff")
... def f():
... print f.__name__
... print f.name
...
>>> f()
wrapper
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in wrapper
File "<stdin>", line 4, in f
AttributeError: 'function' object has no attribute 'name'
更奇怪的是:
>>> def f():
... print f.__name__
... print f.name
...
>>> x = name("jeff")(f)
>>> x.name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'name'
>>> x()
f
jeff
当然,x.name 现在失败了,因为装饰器返回包装器而不是有趣。同时:
>>> f = name("jeff")(f)
>>> f()
wrapper
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in wrapper
File "<stdin>", line 3, in f
AttributeError: 'function' object has no attribute 'name'
此外:
>>> def name(n):
... def decorator(fun):
... fun.name = n
... @wraps(fun)
... def wrapper():
... return fun()
... return wrapper
... return decorator
...
>>> @name("my name jeff")
... def f():
... print f.__name__
... print f.name
...
>>> f()
f
my name jeff
我不是一个蟒蛇忍者,所以如果我遗漏了一些明显的东西,请指出。
【问题讨论】:
-
最后一个脚本,第 4 行,
f或fun? -
很好,应该很有趣,将再次运行,更正
-
你似乎明白你的装饰器返回
wrapper,而不是fun。那么你的问题到底是什么? -
wrapper 在
return fun()中仍然调用fun,我为fun设置了name的属性,为什么它不起作用?如果它不应该工作,为什么x = name("jeff")(f)工作而不是f = name("jeff")(f)?
标签: python python-2.7 python-decorators