具有函数属性

时间:2018-03-08 13:39:43

标签: python python-2.7 python-decorators

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

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

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

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

1 个答案:

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