Python中类装饰器修饰函数时,函数如何访问类内self._count
如何让被类装饰器修饰的函数访问装饰器内部的属性?
首先得明确一个关键点:当你用@decorate_class修饰callname函数时,callname这个变量已经不再指向原来的函数了——它现在是decorate_class类的一个实例。原来的函数被存在了这个实例的_func属性里。
要让被装饰的函数访问装饰器内部的_count,有几种实用的方法:
方法1:调用原函数时传递装饰器实例
你可以在装饰器的__call__方法里,把装饰器自身的实例作为参数传给原函数,这样原函数就能通过这个参数访问_count了。修改后的代码如下:
class decorate_class: def __init__(self, f): self._func = f self._count = 0 def __call__(self, *args, **kargs): self._count += 1 # 把装饰器实例传递给原函数 return self._func(self, *args, **kargs) @decorate_class def callname(decorator, name): print(f"Hello, {name}") # 通过传入的装饰器实例访问_count print(f"这是第 {decorator._count} 次调用") # 调用时只需要传入name参数即可 callname("Alice") callname("Bob")
运行这段代码,你会看到每次调用都能正确打印当前的调用次数。这种方法的好处是函数和装饰器的耦合度较低,只要函数接收这个参数就行,不用硬编码函数名。
方法2:直接通过函数名(装饰器实例)访问属性
因为callname现在是decorate_class的实例,所以你可以直接在函数内部通过callname._count来访问这个属性。代码示例:
class decorate_class: def __init__(self, f): self._func = f self._count = 0 def __call__(self, *args, **kargs): self._count += 1 return self._func(*args, **kargs) @decorate_class def callname(name): print(f"Hello, {name}") # 直接通过函数名访问装饰器实例的_count属性 print(f"这是第 {callname._count} 次调用") callname("Alice") callname("Bob")
这种方法更简洁,但缺点是函数里硬编码了自己的名字,如果后续你修改了函数名,这里的代码也要跟着改,耦合度相对高一些。
原理补充
本质上,类装饰器的工作流程是:
- 当Python解释器遇到
@decorate_class时,会把下面的callname函数作为参数传给decorate_class的构造方法__init__。 - 然后把
callname变量重新赋值为decorate_class的实例。 - 每次调用
callname()时,实际上是调用这个实例的__call__方法,在这个方法里完成计数,再调用原来的函数。
所以只要你能拿到这个装饰器实例的引用,就能访问它的_count属性——上面的两种方法都是基于这个原理实现的。
内容的提问来源于stack exchange,提问作者Abhishek
相关产品推荐
相关产品推荐

