Python 无法在装饰器内设置函数属性

Python 无法在装饰器内设置函数属性,python,python-decorators,Python,Python Decorators,我有这样一个Python代码: from functools import wraps def dec(f): @wraps(f) def wrapper(*args, **kwargs): f.foo = 'foo' value = f() f.foo = 'foo' return value return wrapper @dec def f(): print('Hello, f'

我有这样一个Python代码:

from functools import wraps

def dec(f): 
    
    @wraps(f)
    def wrapper(*args, **kwargs):
        f.foo = 'foo'
        value = f()
        f.foo = 'foo'
        return value
    return wrapper

@dec
def f():
    print('Hello, f')

f()
print(f.foo)
您可以找到就绪代码:


这段代码的问题是,我最终得到了
AttributeError:“function”对象没有属性“foo”
,尽管我使用了functools中的
wrapps
decorator,它应该保留函数的属性范围。知道错误的原因是什么吗?

您正在设置
f
上的属性,但是您正在返回
wrapper
,主范围中的
f
wrapper
函数对象。要使用不太容易混淆的名称进行说明,请执行以下操作:

def dec(f): 
    @wraps(f)
    def wrapper(*args, **kwargs):
        f.foo = 'foo'  # <-- this is the original bar function
        value = f()
        return value

    return wrapper

@dec
def bar():
    print('Hello, f')

bar()  # <-- this is wrapper()
def dec(f):
@包装(f)
def包装(*args,**kwargs):

f、 foo='foo'#
dec
需要返回
wrapper
not
f
。您的装饰程序目前为no-op。只有在调用
f()
时才会创建
foo
属性。如果您希望在“装饰时间”创建它,请将该行移动到
dec
,而不是
wrapper
。修复了该问题,但它仍然不会消除根issue@deceze,请参阅问题中的更新代码。这个问题仍然存在,这不是deceze所建议的。你无缘无故地打了两次f(),我不同意你的看法,@deceze。这实际上就是
functool
wrapps
函数所做的。请参阅此代码-。使用和不使用wrapps装饰程序
wrapps
进行游戏,确保
wrapper
的签名与
f
的签名相似。这并不能使它们成为同一个对象。decorator语法是sugar,用于
bar=dec(bar)
bar
将是
dec
返回的任何内容
dec
返回
wrapper
<代码>栏
包装器
。您没有在该对象上设置属性,因此它不会显示在那里。