我正在实现什么是函数内静态变量的 Python 等效项中描述的装饰器?. 在答案中,装饰器被置于一个正常的功能上,它也在我的环境中工作。
现在我想把装饰器放到一个类方法上。
源代码:
#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_()
Run Code Online (Sandbox Code Playgroud)
预期结果:
1
2
3
Run Code Online (Sandbox Code Playgroud)
实际结果:
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'
Run Code Online (Sandbox Code Playgroud)
我不明白为什么这段代码不起作用。根据错误消息,self.f_.counter不存在但print(self.f_.counter)有效。这里发生了什么事?
c1.f_()相当于C.f_.__get__(c1, C)()(由于描述符协议)。__get__返回method实际被调用的对象。您附加counter到原始函数对象,这不是包装的内容method:它包装了 . 创建的函数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
Run Code Online (Sandbox Code Playgroud)
甚至没有装饰器:
class C:
def f_(self) -> None:
print(self.f_.counter)
self.f_.counter += 1
f_.counter = 1
Run Code Online (Sandbox Code Playgroud)