繁体   English   中英

具有函数属性的Python装饰器

[英]Python decorators with function attributes

我一直在试验装饰器,发现它们之间存在一些有趣的不一致,希望你能帮助我解决它。

首先,我有一个像这样的装饰:

>>> 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现在失败,因为decorator返回包装器而不是很有趣。 与此同时:

>>> 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

我不是一个蟒蛇忍者,所以如果我错过了一些明显的东西请指出来。

你的装饰者如下:

>>> def name(n):
...     def decorator(fun):
...             fun.name = n
...             def wrapper():
...                     return fun()
...             return wrapper
...     return decorator

您正在设置name属性以获得fun ,但您正在返回wrapper 换句话说,你用wrapper替换fun ,它确实没有name属性。

您可以尝试以下方法:

>>> def name(n):
...     def decorator(fun):
...             def wrapper():
...                     return fun()
...             wrapper.name = n
...             return wrapper
...     return decorator

例:

>>> @name("hello")
... def f():
...     print(f.__name__)
...     print(f.name)
...     
>>> f()
wrapper
hello

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM