为什么Python 3的PrettyPrinter与Python 2的表现不同,如何获得相同的行为?

3
当我尝试运行这段代码时:
from pprint import PrettyPrinter

class MyPrettyPrinter(PrettyPrinter):
    def __init__(self, *args, **kwargs):
        PrettyPrinter.__init__(self, *args, **kwargs)
    def format(self, object, context, maxlevels, level):
        (repr, readable, recursive) = PrettyPrinter.format(self, object, context, maxlevels, level)
        return (type(repr)(object), readable, recursive) if isinstance(object, str) else (repr, readable, recursive)

print(MyPrettyPrinter().pformat(['x']))

我在Python 3中得到了不同的输出结果(['x']),而在Python 2中得到了不同的输出结果([x])。

为什么会这样,如何才能获得与Python 2相同的行为?

1个回答

2
这是Python 3内部_format函数的工作原理:
def _format(self, object, stream, indent, allowance, context, level):
    # …
    rep = self._repr(object, context, level - 1)
    max_width = self._width - 1 - indent - allowance
    sepLines = len(rep) > max_width

    if sepLines:
        # … custom repr logic
    write(rep)

正如您所看到的,如果_repr的输出符合单行显示的条件,则不会使用自定义逻辑来生成repr。 self._repr委托给self.format,它实际上只是做了一个更复杂的repr()。因此,如果输出符合单行显示的条件,则仅调用一次;否则,输出未使用,但(这里:序列)元素被拆分成多个部分,并且对子元素再次调用逻辑。
相比之下,Python 2的_format在任何阶段都实现了完全自定义的逻辑,始终为列表中的所有子元素调用自定义格式化程序。这就是为什么您的触发器在Python 2中起作用,但在Python 3中不起作用的原因。
不幸的是,我没有看到任何简单的方法可以在不复制新Python 3实现中的大量逻辑的情况下进行挂接。

+1 哦,有趣。你会称之为一个 bug 吗?对我来说它看起来像是个 bug,但我不确定这是否是有意的... - user541686
我不会称之为一个 bug,因为它有点像是实现细节。但是,文档建议子类化漂亮打印机,但并没有确保每个级别都调用“format”函数,这似乎对我而言有些奇怪。 - poke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接