自定义日志装饰器装饰类方法触发TypeError如何解决?
问题根源
你的类式装饰器直接返回了Logger实例自身的绑定方法,破坏了Python类实例方法的自动绑定机制。装饰普通函数时没有上下文绑定需求所以运行正常,但装饰类的实例方法时,Python不会再自动将类实例作为第一个参数传入原方法,导致原方法缺少self参数,触发参数不匹配的报错。
解决方案
这里给出两种可行的修复方案:
方案1:为Logger类实现描述符协议(推荐,最小改动原有逻辑)
Python中方法的自动绑定是通过描述符的__get__方法实现的,我们只需要为Logger类添加__get__方法,就能适配类方法的调用场景:
from functools import partial class Logger: def __init__(self, logging_type:str = 'debug'): self.logging_type = logging_type def __call__(self, decorated_function:callable): self.func = decorated_function return self # 新增__get__方法处理方法绑定 def __get__(self, instance, owner): if instance is None: return self # 把类实例绑定为第一个参数 return partial(getattr(self, self.logging_type), instance) def debug(self, *args, **kwargs): print("starting function") output = self.func(*args, **kwargs) print("Completing Function") return output
注意这里修改了__call__的返回值,直接返回Logger实例本身,由__get__在方法被调用时处理参数绑定。
方案2:改用闭包形式实现装饰器(更简洁,无绑定问题)
如果没有强制用类实现装饰器的需求,用函数闭包的写法天然规避了绑定问题:
def Logger(logging_type:str = 'debug'): def decorator(func): def wrapper(*args, **kwargs): if logging_type == 'debug': print("starting function") output = func(*args, **kwargs) print("Completing Function") return output # 可扩展其他日志类型逻辑 return wrapper return decorator
测试验证
两种方案都可以正常运行测试代码:
class BigClass: def __init__(self, stuff = 10): self.stuff = stuff @Logger(logging_type="debug") def cool_function(self, input1: int): return self.stuff + input1 test = BigClass() print(test.cool_function(3)) # 输出: # starting function # Completing Function # 13
内容的提问来源于stack exchange,提问作者WolVes
相关产品推荐
相关产品推荐

