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

同一类中定义并使用装饰器的正确方法

同一类中定义并使用装饰器的正确方法

我来帮你搞定这个类内装饰器的问题~你遇到的错误本质很清晰:在类定义的阶段,实例还没创建出来呢,直接把实例方法write_log当装饰器用,Python根本找不到它需要的self参数,自然就会参数混乱报错。

先拆解下你出错的原因:
你的write_log是个实例方法,第一个参数必须是self,但当你写@write_log("This is a log.")时,Python会立刻执行这个调用——这时候它把字符串"This is a log."当成了self参数,可函数还需要一个log参数没传,所以就报了“缺少log参数”的错误,完全是参数顺序搞混了。

下面给你两种可行的正确写法,都能完美达到你的预期:

方法一:调整装饰器结构,从调用参数中获取实例

这种写法不需要把装饰器绑定到类,直接通过方法调用时的参数拿到self:

from functools import wraps

class BaseClass:
    def __init__(self, id):
        self.id = id

    # 装饰器工厂:先接收日志内容
    def write_log(log):
        def decorator(initial_func):
            # 保留原方法的元信息,避免后续出现奇怪问题
            @wraps(initial_func)
            def wrapper(*args, **kwargs):
                # 被装饰的是实例方法,第一个参数肯定是self
                self = args[0]
                print(f"{self.id}: {log}")
                return initial_func(*args, **kwargs)
            return wrapper
        return decorator

    @write_log("This is a log.")
    def my_method(self, some_param):  # 要对应你调用时传的参数2
        print(f"This is a test.")

# 实例化时必须传id参数,和你预期的输出对应传6
test = BaseClass(6)
test.my_method(2)

运行这段代码,会精准输出你想要的内容:

6: This is a log.
This is a test.

方法二:把装饰器设为静态方法

如果你想让装饰器属于类的一部分,可以把它标记为静态方法,明确它不需要self或类参数:

from functools import wraps

class BaseClass:
    def __init__(self, id):
        self.id = id

    @staticmethod
    def write_log(log):
        def decorator(initial_func):
            @wraps(initial_func)
            def wrapper(*args, **kwargs):
                self = args[0]
                print(f"{self.id}: {log}")
                return initial_func(*args, **kwargs)
            return wrapper
        return decorator

    @write_log("This is a log.")
    def my_method(self, some_param):
        print(f"This is a test.")

test = BaseClass(6)
test.my_method(2)

效果和方法一完全一致,只是把装饰器归到了类的静态方法范畴里。

另外还要修正你原代码里的两个小疏漏:

  • __init__方法要求传id参数,实例化时不能空着,得写BaseClass(6);
  • my_method要接收你调用时传的2,所以方法定义里必须加一个参数(比如上面的some_param)。

最后说下你尝试加self在装饰器前为什么会失败:比如写@self.write_log(...),但在类定义阶段,self这个变量根本不存在——它只有在实例方法内部才有意义,Python直接会报NameError,完全是合理的报错。

备注:内容来源于stack exchange,提问作者חיים קרופניק

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.16 10:32:57