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

自定义日志装饰器装饰类方法触发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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 00:36:03