如何让Python自定义Sequence集合支持pprint格式化输出?
解决自定义Sequence类的pprint格式化问题
问题原因
pprint模块的格式化逻辑基于具体类型匹配,而非抽象基类。它默认仅对原生序列(list、tuple等)执行换行、缩进处理,即便你的类继承了collections.abc.Sequence,pprint也不会自动将其识别为可拆分的序列,只会直接调用__repr__输出所有内容。
解决方案1:实现__pretty__钩子(Python 3.8+)
pprint在Python 3.8及以上版本支持__pretty__方法,允许自定义对象直接复用pprint的内置格式化逻辑。修改你的MySequence类,添加该方法:
import collections from pprint import PrettyPrinter from dataclasses import dataclass, field from typing import List class MySequence(collections.abc.Sequence): def __init__(self, iterable): self.elements = list(iterable) def __iter__(self): return iter(self.elements) def __contains__(self, value): return value in self.elements def __getitem__(self, index): return self.elements.__getitem__(index) def __len__(self): return len(self.elements) def __repr__(self): return self.elements.__repr__() def __pretty__(self, printer: PrettyPrinter, cycle): # 复用pprint对list的格式化逻辑 return printer._format(self.elements, cycle) # 测试dataclass @dataclass class MyClass1: halloffame: List = field(default_factory=lambda: ["x" * 80]*4) @dataclass class MyClass2: halloffame: MySequence = field(default_factory=lambda: MySequence(["x" * 80]*4)) # 验证输出 from pprint import pprint pprint(MyClass1()) pprint(MyClass2())
解决方案2:注册自定义格式化器(兼容旧Python版本)
如果使用Python 3.7及以下版本,可通过注册自定义格式化函数到pprint的分发器,让pprint按list的规则处理MySequence:
import collections from pprint import PrettyPrinter from dataclasses import dataclass, field from typing import List class MySequence(collections.abc.Sequence): # 保持原有实现不变 def __init__(self, iterable): self.elements = list(iterable) def __iter__(self): return iter(self.elements) def __contains__(self, value): return value in self.elements def __getitem__(self, index): return self.elements.__getitem__(index) def __len__(self): return len(self.elements) def __repr__(self): return self.elements.__repr__() # 注册MySequence的格式化函数 def format_mysequence(obj, stream, indent, allowance, context, level): PrettyPrinter._format_list(obj.elements, stream, indent, allowance, context, level) PrettyPrinter._dispatch[MySequence] = format_mysequence # 测试dataclass @dataclass class MyClass1: halloffame: List = field(default_factory=lambda: ["x" * 80]*4) @dataclass class MyClass2: halloffame: MySequence = field(default_factory=lambda: MySequence(["x" * 80]*4)) # 验证输出 from pprint import pprint pprint(MyClass1()) pprint(MyClass2())
验证效果
两种方案都会让MyClass2的pprint输出与MyClass1完全一致:
MyClass1(halloffame=['xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx']) MyClass2(halloffame=['xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'])
内容的提问来源于stack exchange,提问作者BorjaEst
相关产品推荐
相关产品推荐

