Python类内用functools wraps装饰器报错:缺少func参数
解决类内实例方法作为装饰器的TypeError问题
你遇到的TypeError: adder() missing 1 required positional argument: 'func',本质是类内的实例方法不能直接用作装饰器。
因为装饰器在类定义阶段就会被执行(也就是当你写@adder修饰oper时,Python会立刻调用adder(oper)),但此时Inherit类还没有创建任何实例,实例方法adder需要的第一个参数self无法自动传入——本来实例方法的调用逻辑是实例.adder(func),但类定义阶段没有实例,直接调用adder(oper)就会少传一个self参数,Python便误以为缺少的是func。
方案一:将装饰器改为静态方法
静态方法不需要绑定实例或类,没有self参数,适合这种不需要访问类/实例属性的装饰器。修改后代码如下:
from functools import wraps class Parent(): def __init__(self, a): self.a = a def oper(self, b): return self.a + b class Inherit(Parent): @staticmethod def adder(func): @wraps(func) def wrapping(*args, **kwargs): # 实例方法的第一个参数是self,不能对其平方,仅处理后续业务参数 new_args = [args[0]] + [i**2 for i in args[1:]] return func(*new_args, **kwargs) return wrapping @adder def oper(self, b): return super().oper(b) a = Parent(10) print(a.oper(10)) # 输出20 b = Inherit(10) print(b.oper(10)) # 输出10 + 10² = 110
方案二:将装饰器移到类外部
如果装饰器不需要和类绑定,直接定义在类外更简洁:
from functools import wraps def adder(func): @wraps(func) def wrapping(*args, **kwargs): new_args = [args[0]] + [i**2 for i in args[1:]] return func(*new_args, **kwargs) return wrapping class Parent(): def __init__(self, a): self.a = a def oper(self, b): return self.a + b class Inherit(Parent): @adder def oper(self, b): return super().oper(b) a = Parent(10) print(a.oper(10)) # 20 b = Inherit(10) print(b.oper(10)) # 110
另外需要注意:你原代码的装饰器逻辑有个隐藏问题——把所有args都平方,包括实例方法的第一个参数self,这会导致调用父类方法时传入错误的self对象。上面的代码已经修正了这个问题,只对self之后的业务参数进行平方操作。
内容的提问来源于stack exchange,提问作者user20426821
相关产品推荐
相关产品推荐

