我一直在尝试使用装饰器并发现它们之间存在一些有趣的不一致,希望你能帮助我解决它。
首先,我有一个像这样的装饰者:
>>> 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
我不是一个蟒蛇忍者,所以如果我错过了一些明显的东西,请指出它。
答案 0 :(得分:2)
你的装饰师如下:
>>> def name(n):
... def decorator(fun):
... fun.name = n
... def wrapper():
... return fun()
... return wrapper
... return decorator
您为name
设置了fun
属性,但是您正在返回wrapper
。
换句话说,您将fun
替换为wrapper
,确实没有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