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

如何为Basis派生类统一配置Python自定义Pretty Printer?

问题分析与解决方案

问题根源

  1. 无自定义__repr__时仅Collector2触发的原因
    Collector的__init__仅写了pass,没有调用父类的初始化方法,导致实例没有正确构建OrderedDict的底层结构。pprint的_dispatch默认会根据对象的实际结构匹配规则,空的未初始化Collector会被当成普通OrderedDict处理,而不是匹配到Basis的绑定规则;Collector2因为初始化了键值对,完成了OrderedDict结构构建,所以能触发自定义打印。

  2. 启用Basis的__repr__后完全不触发的原因
    pprint的优先级逻辑是:如果对象有自定义__repr__(非内置容器继承的方法),会直接调用该方法,跳过_dispatch中的自定义绑定规则,所以你的自定义打印方法被忽略了。

解决方案:基于类型匹配的自定义打印器

要实现对所有Basis派生类生效,不管初始化逻辑和__repr__是否存在,直接基于类型检查绑定打印规则即可,替代原来依赖__repr__的方式。

示例代码:

from collections import OrderedDict
import pprint

class Basis(OrderedDict):
    def __str__(self):
        return f"Basis({super().__str__()})"
    
    # 无论是否启用该__repr__,打印器都能正常工作
    # def __repr__(self):
    #     return self.__str__()

class Collector(Basis):
    def __init__(self):
        pass  # 即使仅pass也不影响打印器触发

class Collector2(Basis):
    def __init__(self):
        super().__init__({"a":1, "b":2})

class ODPPrinter(pprint.PrettyPrinter):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 直接将Basis类型映射到自定义打印方法
        self._dispatch[Basis] = self._print_basis
    
    def _print_basis(self, obj, stream, indent, allowance, context, level):
        # 自定义打印逻辑,可根据需求修改
        stream.write(f"[自定义Basis打印] {obj.__str__()}")

# 测试验证
col = Collector()
col2 = Collector2()

printer = ODPPrinter()
printer.pprint(col)
printer.pprint(col2)

关键说明

  • 类型优先匹配:直接基于Basis类型绑定打印方法,只要是Basis的派生类实例,无论初始化是否完整,都会触发自定义逻辑。
  • 兼容自定义__repr__:pprint的类型匹配优先级高于自定义__repr__调用,即使Basis重载了__repr__,自定义打印器依然生效。
  • 可选优化:如果希望Collector实例具备正常OrderedDict的功能,建议在其__init__中添加super().__init__(),不过即使不做这个优化,打印器也能正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 10:22:07