【问题标题】:Python decorators with function attributes具有函数属性的 Python 装饰器
【发布时间】: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 行,ffun?
  • 很好,应该很有趣,将再次运行,更正
  • 你似乎明白你的装饰器返回wrapper,而不是fun。那么你的问题到底是什么?
  • wrapper 在return fun() 中仍然调用fun,我为fun 设置了name 的属性,为什么它不起作用?如果它不应该工作,为什么x = name("jeff")(f) 工作而不是f = name("jeff")(f)

标签: python python-2.7 python-decorators


【解决方案1】:

你的装饰器如下:

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

您正在为fun 设置name 属性,但您正在返回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

【讨论】:

  • 但是wrapper 仍然调用fun,不是吗?另外,为什么x = name("jeff")(f) 可以工作,而f = name("jeff")(f) 不行,我在这两种情况下都替换了fun
  • 哦,我明白了,因为 f 是全局变量。
猜你喜欢
  • 2017-01-06
  • 1970-01-01
  • 2023-03-31
  • 2014-07-21
  • 2013-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多