Python 2.7中装饰类方法引发unbound method TypeError问题求助
解决类外部装饰classmethod后调用报错的问题
你遇到的这个TypeError是因为装饰后的方法丢失了classmethod的特性,被当成普通的实例方法处理了。让我一步步拆解问题并给出解决办法:
问题根源
在Python 2中,@classmethod装饰的方法是一个descriptor(描述符),当你通过类访问它时,会自动绑定到类本身。但当你把A.demo_method传给装饰器时,你拿到的是一个unbound method对象,装饰器返回的wrapper是普通函数,再通过setattr设回类属性后,这个属性就变成了普通函数,不再具备classmethod的自动绑定逻辑。此时调用A.demo_method(1),Python会默认把它当作实例方法,要求第一个参数是类实例,而你传入的是int类型的1,自然就触发了错误。
解决方案
方案1:装饰后重新包装为classmethod
修改你的装饰器,让它返回的wrapper被classmethod包装,这样就能保留原方法的类绑定特性:
class A(object): @classmethod def demo_method(cls, a): print(a) def decorator(function): from functools import wraps @wraps(function) def wrapper(*args, **kwargs): return_value = function(*args, **kwargs) return return_value # 将wrapper转换为classmethod,恢复类绑定逻辑 return classmethod(wrapper) setattr(A, 'demo_method', decorator(A.demo_method)) A.demo_method(1) # 现在正常输出1
方案2:先提取原始函数再装饰
另一种方式是先取出classmethod底层的原始函数,装饰后再重新包装成classmethod:
class A(object): @classmethod def demo_method(cls, a): print(a) def decorator(function): from functools import wraps @wraps(function) def wrapper(*args, **kwargs): return_value = function(*args, **kwargs) return return_value return wrapper # 取出classmethod的原始函数,装饰后重新包装 original_func = A.demo_method.__func__ setattr(A, 'demo_method', classmethod(decorator(original_func))) A.demo_method(1) # 同样正常输出1
验证效果
运行修改后的代码,你会发现demo_method可以正常接收参数并打印,不再抛出TypeError。
内容的提问来源于stack exchange,提问作者Sumit
相关产品推荐
相关产品推荐

