pprint 排序字典但不是集合?
问题描述
我知道 dicts 和 sets 没有顺序,所以相等的 sets 或 dicts 可能会打印不同的内容(所有测试都使用 Python 3.6.1):
>>>对于 {0, 8}, {8, 0}, {0:0, 8:8}, {8:8, 0:0} 中的 obj:打印(对象){0, 8}{8, 0}{0:0, 8:8}{8:8, 0:0}
我刚刚意识到 pprint
(pretty-print") 对 dicts 进行排序,但不对集合进行排序:
>>>对于 {0, 8}, {8, 0}, {0:0, 8:8}, {8:8, 0:0} 中的 obj:pprint.pprint(obj){0, 8}{8, 0}{0:0, 8:8}{0:0, 8:8}
它的文档还说字典在计算显示之前按键排序".但是为什么它也不排序集合呢?在我看来并不漂亮.有没有办法制作排序集?也在嵌套结构中,因为这是 pprint
的主要目的.
这是在 问题中提出的27495,这是一个错误,而不仅仅是一个设计选择,但显然还没有解决.
以下是问题中的另一个示例,它可能更清楚地说明了您在 Python 3 中识别的行为:
<块引用>>>>导入字符串,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))设置(['0','1','2','3','4','5','6','7','8','9'])
我认为是 Python 3 和 Python 2 之间的不一致,以及单行多行行为之间的不一致,导致了这个错误.
对于 dict
s,一个类似的例子说明了输出在 Python 3 或 2 中的排序,因为它应该是:
>>>pprint.pprint({i:None for i in set(string.digits)}){'0':无,1":无,2":无,3":无,4":无,5":无,6":无,7":无,8":无,9":无}
但是,对于 Python 3.6,pprint
对 dict
进行排序可能会令人惊讶,因为它们 已现在订购.但是,由于这只是一个实现细节(目前),我想 pprint
没有义务维护插入顺序(还),这样做会破坏 pprint
始终对 dict
s 进行排序的 Python 版本的自身一致性.
I know that dicts and sets aren't ordered, so equal sets or dicts may print differently (all tests with 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}
And I just realized that pprint
("pretty-print") sorts dicts but not sets:
>>> 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}
It's documentation also says "Dictionaries are sorted by key before the display is computed". But why doesn't it also sort sets? Doesn't seem pretty to me. And is there a way to make it sort sets? Also inside nested structures, as that's a main purpose of pprint
.
This was raised in issue 27495 and it is a bug, rather than just a design choice, but apparently has not yet been resolved.
Here is another example from the issue that illustrates perhaps more obviously the behavior you identify in Python 3:
>>> import string, pprint >>> pprint.pprint(set(string.digits)) {'7', '1', '9', '8', '3', '0', '2', '5', '6', '4'}
The same applies for frozenset()
too, but note that multi-line pprint
outputs are sorted in Python 3, for example:
>>> pprint.pprint(set(string.digits), width=1) {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
However, in Python 2, the output from the same original code is sorted:
>>> pprint.pprint(set(string.digits)) set(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])
I think it is the inconsistency between Python 3 and Python 2, and between the single-line multi-line behavior, that makes this a bug.
For dict
s, a similar example, illustrates as you note, that the output is sorted in either Python 3 or 2, as it should be:
>>> 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}
However, for Python 3.6, it could be considered surprising that pprint
sorts dict
s since they are ordered now. However, since this is just an implementation detail (for now) I guess there is no obligation for pprint
to maintain the insertion order (yet), and doing so would break pprint
's own consistency across Python versions of always sorting dict
s.
相关文章