【问题标题】:pprint sorting dicts but not sets?pprint 排序字典但不是集合?
【发布时间】:2017-07-10 15:48:14
【问题描述】:

我知道 dicts 和 sets 没有排序,所以相等的 sets 或 dicts 可能会打印不同的内容(所有测试都使用 Python 3.6.1):

>>> for obj in {0, 8}, {8, 0}, {0:0, 8:8}, {8:8, 0:0}:
        print(obj)

{0, 8}
{8, 0}
{0: 0, 8: 8}
{8: 8, 0: 0}

我刚刚意识到 pprint (“pretty-print”) 对 dicts 进行排序,而不是对集合进行排序:

>>> for obj in {0, 8}, {8, 0}, {0:0, 8:8}, {8:8, 0:0}:
        pprint.pprint(obj)

{0, 8}
{8, 0}
{0: 0, 8: 8}
{0: 0, 8: 8}

它的文档还说“字典在计算显示之前按键排序”。但是为什么它也不排序集合呢?在我看来并不漂亮。有没有办法制作排序集?也在嵌套结构中,因为这是 pprint 的主要目的。

【问题讨论】:

  • 我猜它不支持集合,但你可以继承 pprint.PrettyPrinter 并覆盖 pformat 来处理集合...

标签: python python-3.x dictionary set pprint


【解决方案1】:

这是在issue 27495 中提出的,这是一个错误,而不仅仅是设计选择,但显然尚未解决。

以下是问题中的另一个示例,它可能更清楚地说明了您在 Python 3 中识别的行为:

>>> import string, pprint
>>> pprint.pprint(set(string.digits))
{'7', '1', '9', '8', '3', '0', '2', '5', '6', '4'}

这同样适用于frozenset(),但请注意,多行pprint 输出在 Python 3 中排序,例如:

>>> pprint.pprint(set(string.digits), width=1)
{'0',
 '1',
 '2',
 '3',
 '4',
 '5',
 '6',
 '7',
 '8',
 '9'}

但是,在 Python 2 中,相同原始代码的输出是排序的:

>>> pprint.pprint(set(string.digits))
set(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])

我认为是 Python 3 和 Python 2 之间的不一致,以及单行多行行为之间的不一致,导致了这个错误。

对于dicts,一个类似的例子说明了输出在 Python 3 或 2 中的排序,应该是这样的:

>>> pprint.pprint({i:None for i in set(string.digits)})
{'0': None,
 '1': None,
 '2': None,
 '3': None,
 '4': None,
 '5': None,
 '6': None,
 '7': None,
 '8': None,
 '9': None}

但是,对于 Python 3.6,pprint 排序 dicts 可能会令人惊讶,因为它们是 are ordered now。但是,由于这只是一个实现细节(目前),我想pprint 没有义务维护插入顺序(还),这样做会破坏pprint 在 Python 版本中始终排序的自身一致性dicts.

【讨论】:

  • 不,它们现在没有排序,这是 cPython 的一个实现细节,其他实现可以将 dicts 实现为无序并且仍然符合规范,只要求在某些情况下使用映射(PEP468 , PEP520) 是保序的。不同的实现可以选择专门处理这些情况并保持无序的 dict 实现。在这正式成为规范的一部分之前,不应将 dicts 视为保留顺序,即使这样做也会破坏向后兼容性。
  • 谢谢。也许我应该自己寻找并找到该问题报告。真的很奇怪它如何对某些东西进行分类,但对其他东西却没有。关于有序字典的好点。如果这确实得到保证,我想 pprint 真的不能再对它们进行排序了,这会有点可悲,因为不那么漂亮了。
  • 但是pprint 的工作方式并不是一个实现细节,这就是它首先成为一个错误的原因。 pprint 只能依赖于现有的 dict 顺序,如果这是在语言规范中定义的。只要不是,选项就只有排序,不排序或显式检查我们是否在 cPython >= 3.6 上。
  • @mata 我想我们同意,我只是在观察,我知道你不能依赖实现细节。顺便说一句,它最终很可能成为语言规范twitter.com/raymondh/status/850102884972675072
  • 或者...嗯...也许他们只会让OrderedDictdict 完全相同,除非有订单保证(而不是像现在这样的额外实现)。我的意思是,据我了解,新的dict 实现中的顺序是一个副作用,而实际目标是让它更有效率。也许有人会想出一个更有效的dict 实现,它不会保持秩序。然后有了订单保证,他们就不能使用它(不破坏东西)。所以有理由不保证。
猜你喜欢
  • 2020-12-16
  • 1970-01-01
  • 2013-12-08
  • 2011-12-25
  • 2013-11-29
  • 2018-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多