如何为Basis派生类统一配置Python自定义Pretty Printer?
问题分析与解决方案
问题根源
无自定义
__repr__时仅Collector2触发的原因
Collector的__init__仅写了pass,没有调用父类的初始化方法,导致实例没有正确构建OrderedDict的底层结构。pprint的_dispatch默认会根据对象的实际结构匹配规则,空的未初始化Collector会被当成普通OrderedDict处理,而不是匹配到Basis的绑定规则;Collector2因为初始化了键值对,完成了OrderedDict结构构建,所以能触发自定义打印。启用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
相关产品推荐
相关产品推荐

