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

类实现的装饰器用于类方法时为何报‘缺少self参数’错误?

类装饰器应用于类方法报错的原因与解决方法

报错原因

类中的方法在被实例访问时,Python会自动将实例作为第一个参数(self)传递给方法,这是方法绑定的核心机制。

但你实现的to_uppercase装饰器是一个类:当用它装饰类方法get_base_string时,原方法会被替换成to_uppercase的实例。而这个装饰器实例并没有实现描述器协议的__get__方法,无法参与Python的方法绑定流程——Python不会自动把类实例s作为参数传递给装饰器的__call__方法,导致原方法get_base_string缺少必需的self参数,最终抛出TypeError。

简单来说:普通函数被装饰后直接传参即可调用,但类方法需要绑定到实例,你的装饰器类没处理这个绑定逻辑,导致原方法拿不到self。

修复方案

要让装饰器支持类方法,需要实现描述器协议的__get__方法,让装饰器实例能绑定到类实例上。以下是两种可行的修改方式:

方式一:用lambda实现绑定

class to_uppercase:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        return self.func(*args, **kwargs).upper()

    def __get__(self, instance, owner):
        # 将类实例绑定到原方法,返回可调用对象
        return lambda *args, **kwargs: self.func(instance, *args, **kwargs).upper()

方式二:用functools.partial优雅处理绑定

import functools

class to_uppercase:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        return self.func(*args, **kwargs).upper()

    def __get__(self, instance, owner):
        # 借助partial将实例绑定到__call__方法
        return functools.partial(self.__call__, instance)

修改后测试代码,就能正常运行:

class base_string:
    def __init__(self, base):
        self.base = base

    @to_uppercase
    def get_base_string(self):
        return self.base

s = base_string('word worD')
print(s.get_base_string())  # 输出: WORD WORD

替代方案:使用函数式装饰器

如果不想手动实现描述器,直接用函数式装饰器更简单,它默认会处理方法绑定问题:

def to_uppercase(func):
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs).upper()
    return wrapper

这个版本既可以装饰普通函数,也能直接装饰类方法,无需额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 08:30:44