Python pprint模块递归处理机制与自定义格式化输出问题
Python pprint自定义格式化问题修复
问题复现
运行自定义PrettyPrinter子类代码时,出现首个嵌套子列表浮点数未按指定规则格式化的问题,同时需要实现单行输出、数值对齐的打印效果。
测试代码
import pprint tmp = [[-3.3724829788320254e-06, 8.789645278006741e-05, -0.03094601113910861], [-0.0001309722558718793, -2.6760843426808773e-05, 8.351451616757592e-06, 0.9999999910301892]] class FormatPrinter(pprint.PrettyPrinter): def __init__(self, formats): super(FormatPrinter, self).__init__(compact=True) self.formats = formats def format(self, obj, ctx, maxlvl, lvl): if type(obj) in self.formats: return self.formats[type(obj)] % obj, 1, 0 return pprint.PrettyPrinter.format(self, obj, ctx, maxlvl, lvl) FormatPrinter({float: "%0.2f", int: "%06X"}).pprint(tmp)
实际异常输出(Python 3.8.12 Jupyter环境)
[[-3.3724829788320254e-06, 8.789645278006741e-05, -0.03094601113910861], [-0.00, -0.00, 0.00, 1.00]]
目标效果
- 所有浮点数按保留2位小数规则格式化
- 输出不换行
- 正数前补充空格,所有数值纵向对齐,效果如下:
[[-0.00, 0.00, -0.03], [-0.00, -0.00, 0.00, 1.00]]
注:原始数据第一个子列表第二个值为正,格式化后为正0.00,和提问中写的-0.00有差异,是原始值正负属性导致的。
问题根因
- 首个子列表未格式化:
pprint.PrettyPrinter默认width=80,打印时会先判断容器原生repr的长度,若当前行剩余宽度可容纳整个子列表的原生repr,就直接输出repr结果,不会递归调用自定义format方法处理内部元素。 - 换行问题:默认宽度不足时pprint会自动折行,需要调整宽度参数强制单行输出。
- 对齐问题:原格式化字符串
%0.2f不会为正数补符号位空格,导致正负数字长度不一致、无法对齐。
修复代码
import pprint tmp = [[-3.3724829788320254e-06, 8.789645278006741e-05, -0.03094601113910861], [-0.0001309722558718793, -2.6760843426808773e-05, 8.351451616757592e-06, 0.9999999910301892]] class FormatPrinter(pprint.PrettyPrinter): def __init__(self, formats): # width设为极大值,强制单行输出+递归遍历所有元素执行自定义格式化 super(FormatPrinter, self).__init__(compact=True, width=10**6) self.formats = formats def format(self, obj, ctx, maxlvl, lvl): if type(obj) in self.formats: return self.formats[type(obj)] % obj, 1, 0 return pprint.PrettyPrinter.format(self, obj, ctx, maxlvl, lvl) # 浮点数格式改为% .2f:强制显示符号位,正数用空格占位,实现自动对齐 FormatPrinter({float: "% .2f", int: "%06X"}).pprint(tmp)
关键修改说明
- 初始化父类时传入
width=10**6:一方面强制所有内容单行输出,另一方面让pprint递归遍历所有内部元素,不会直接输出容器原生repr。 - 浮点数格式化字符串改为
"% .2f":格式规则为保留2位小数,始终保留符号位,正数符号位用空格填充,保证所有格式化后的浮点数长度一致,自动对齐。
运行结果
[[-0.00, 0.00, -0.03], [-0.00, -0.00, 0.00, 1.00]]
内容的提问来源于stack exchange,提问作者BlGene
相关产品推荐
相关产品推荐

