You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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")

这种方法更简洁,但缺点是函数里硬编码了自己的名字,如果后续你修改了函数名,这里的代码也要跟着改,耦合度相对高一些。

原理补充

本质上,类装饰器的工作流程是:

  1. 当Python解释器遇到@decorate_class时,会把下面的callname函数作为参数传给decorate_class的构造方法__init__。
  2. 然后把callname变量重新赋值为decorate_class的实例。
  3. 每次调用callname()时,实际上是调用这个实例的__call__方法,在这个方法里完成计数,再调用原来的函数。

所以只要你能拿到这个装饰器实例的引用,就能访问它的_count属性——上面的两种方法都是基于这个原理实现的。

内容的提问来源于stack exchange,提问作者Abhishek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:25:17