【问题标题】:Pretty print Python dict漂亮的打印 Python 字典
【发布时间】:2020-11-10 16:30:12
【问题描述】:

我习惯于使用pprint 模块来漂亮地打印我的内置Python 容器对象,例如dictlist。然而,在打印时,我面临着强制容器在包含的对象上使用__str__ 的困难(因为默认情况下,它们在包含的对象上使用__repr__ 方法),同时保持漂亮的打印。

这是一个例子:

import pprint

class H:
    """ Example of a contained object
    """
    def __str__(self):
        return "This is my H class string representation"

    def __repr__(self):
        return "H()"

d = {
    'a': H(),
    'b': {
        'c': H(),
        'd': H()
    }
}

pprint.pprint(d, width=10)

返回漂亮的打印结果:

{'a': H(),
 'b': {'c': H(),
       'd': H()}}

但正如您所见,__repr__ 在 H 对象上被调用。

为了强制字典对包含的对象使用__str__,有人建议使用join()。比如:

print("{" + "\n".join("{!r}: {!s},".format(k, v) for k, v in d.items()) + "}")

返回:

{'a': This is my H class string representation,
'b': {'c': H(), 'd': H()},}

显然不适用于嵌套字典,而且在这种情况下也无法使用pprint,因为在连接之后我们会得到一个字符串。

理想情况下我想要打印的是:

{'a': This is my H class string representation,
 'b': {'c': This is my H class string representation,
       'd': This is my H class string representation}}

对于上下文,我的字典的键始终是字符串,值是有问题的对象,例如H(),我需要__str__ 表示而不是__repr__

【问题讨论】:

  • 你能让__repr__返回self.__str__()吗?如果是,它会按您的预期工作
  • “我面临着强制容器在包含的对象上使用 __str__ 的困难” - pprint 不这样做是有充分理由的。当__str____repr__ 不同时,__str__ 输出通常不会与周围的文本明确分隔,或者与无关类型的__str__ 输出区分开来。您可能会对您正在尝试的内容感到困惑。
  • 看看你是如何无意识地使用repr 输出而不是str 输出作为你的dicts 键的。想象一下,如果pprint 使用了str,而您的其中一个键是'1: 2'。或者想象一下,如果您的 dict 中有异常,因为异常的 str 输出与其参数(或参数元组)的 str 相同。
  • 我确实理解容器使用__repr__ 的充分理由,以避免歧义。但是在这种特殊情况下,我知道我的每个对象是什么以及它们的行为方式。我的程序涉及解析这些字典的字符串输出,所以我需要它们的字符串表示。我想保持__repr__ 原样以避免歧义。
  • pprint source 不是很大。为什么不直接修改它以获得适合您需求的模块(例如称为pprint2)?

标签: python string dictionary printing pretty-print


【解决方案1】:

Python 允许动态更改类中的方法。所以你可以暂时让__repr__ 成为__str__

def str_pprint(d):
    sv = H.__repr__
    H.__repr__ = H.__str__
    pprint.pprint(d, width=10)
    H.__repr__ = sv

str_pprint(d)

使用您的数据,它会按预期提供:

{'a': This is my H class string representation,
 'b': {'c': This is my H class string representation,
       'd': This is my H class string representation}}

注意:这会全局更改类属性,因此如果需要多个执行线程(多线程程序或中断处理程序),则不能使用它。

【讨论】:

  • 这是线程不安全的(并且在存在__del__ 方法等相同线程中断的情况下不安全)。
  • @user2357112supportsMonica:我主要将 Python 用于简单的线性脚本,所以我什至没有想过要警告它。现在完成了,感谢您的评论...
  • 是的,我同意这是非常不安全的线程。但是,自从您发出警告后,我会将其标记为已接受。同时,我将研究 pprint 模块,看看我是否可以在这里调整到我的目的。谢谢大家的回答。
猜你喜欢
  • 2015-01-12
  • 2016-11-26
  • 2016-09-03
  • 2014-05-12
  • 1970-01-01
  • 2011-03-14
  • 2017-02-22
  • 2019-04-23
相关资源
最近更新 更多