类实现的装饰器用于类方法时为何报‘缺少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
相关产品推荐
相关产品推荐

