python - 奇怪的AttributeError仅在赋值时

标签 python decorator

我正在实现 What is the Python equivalent of static variables inside a function? 中描述的装饰器.在答案中,装饰器具有正常功能,并且在我的环境中也可以使用。
现在我想把装饰器放到一个类方法上。
源代码:

#decorator
def static_variabls(**kwargs):
    def new_func(old_func):
        for key in kwargs:
            setattr(old_func, key, kwargs[key])
        return old_func
    return new_func

class C:
    @static_variabls(counter = 1)
    def f_(self) -> None:
        print(self.f_.counter)
        self.f_.counter += 1

c1 = C()
c1.f_()
c1.f_()
c1.f_()
预期结果:
1
2
3
实际结果:
1
Traceback (most recent call last):
  File "1.py", line 16, in <module>
    c1.f_()
  File "1.py", line 13, in f_
    self.f_.counter += 1
AttributeError: 'method' object has no attribute 'counter'
我不明白为什么这段代码不起作用。根据错误信息,self.f_.counter不存在,但 print(self.f_.counter)作品。这里发生了什么事?

最佳答案

c1.f_()相当于C.f_.__get__(c1, C)() (由于描述符协议(protocol))。 __get__返回 method实际被调用的对象。你附上了counter到原始函数对象,这不是 method wraps:包装def new_func创建的函数.
请注意,对于一个更简单的装饰器,您也有同样的问题,它对属性及其初始值进行了硬编码。

def add_counter(f):
    f.counter = 1
    return f


class C:
    @add_counter
    def f_(self) -> None:
        print(self.f_.counter)
        self.f_.counter += 1
甚至没有装饰器:
class C:
    def f_(self) -> None:
        print(self.f_.counter)
        self.f_.counter += 1

    f_.counter = 1

关于python - 奇怪的AttributeError仅在赋值时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62968862/

相关文章:

python - 是否可以在运行时替换 Python 函数/方法装饰器?

python - 装饰链

python - 如何绘制 K 均值并打印集群外的点

python - qtextbrowser 右对齐或居中对齐

python - 如何测试 View 是否装饰有 "login_required"(Django)

python - 如何使装饰器对调试器透明

TypeScript 属性装饰器 : access to other properties

Python控制台不显示函数的输出

Python NumPy : Efficiently get rows containing min value of column for each unique tuple of 3 other columns

python - 每个转换器以浮点形式读取数据