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

使用装饰器猴子补丁class.__str__方法失效问题排查

问题根源分析

你的装饰器结构出现了错误,导致MyClass最终被替换成了内部的decorator函数,而不是你期望的修改了__str__方法的类。具体过程是这样的:

  1. 当你使用@str_patcher装饰MyClass时,Python会执行MyClass = str_patcher(MyClass)。
  2. str_patcher接收原MyClass作为klass参数,然后返回内部定义的decorator函数。这意味着现在MyClass这个名称指向的是decorator函数,而不是原来的类。
  3. 当你调用MyClass(a=1, b=2, c=3)时,本质是调用decorator(a=1, b=2, c=3)。这个函数内部确实修改了原klass(最初的MyClass)的__str__方法,但最后返回的是klass本身——也就是原类对象,而不是类的实例。
  4. 所以print(...)打印的是类对象,而不是实例,自然输出<class __main__.MyClass>。
修复方案

有两种简单的修复方式,取决于你是否需要装饰器支持额外参数:

方案1:简化装饰器(无额外参数场景)

直接去掉不必要的嵌套,让装饰器直接接收类作为参数,修改后返回类:

def str_patcher(klass):
    def __str__(self):
        items = {key: value for key, value in self.__dict__.items() if not key.startswith("_")}
        return f"{type(self).__qualname__}({items})"
    klass.__str__ = __str__
    return klass

@str_patcher
class MyClass:
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)

# 测试
print(MyClass(a=1, b=2, c=3))  # 输出:MyClass({'a': 1, 'b': 2, 'c': 3})

方案2:保留嵌套结构(支持未来扩展参数)

如果以后需要给装饰器加参数(比如自定义过滤规则),可以调整成“装饰器工厂”的结构,使用时需要调用str_patcher():

def str_patcher():
    def decorator(klass):
        def __str__(self):
            items = {key: value for key, value in self.__dict__.items() if not key.startswith("_")}
            return f"{type(self).__qualname__}({items})"
        klass.__str__ = __str__
        return klass
    return decorator

@str_patcher()  # 注意这里要加括号
class MyClass:
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)

# 测试
print(MyClass(a=1, b=2, c=3))  # 输出:MyClass({'a': 1, 'b': 2, 'c': 3})

内容的提问来源于stack exchange,提问作者Alan Bagel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 03:02:44