[英]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.