pprint的排序规则,但不是集合?

时间:2022-02-23 18:06:56

I know that dicts and sets aren't ordered, so equal sets or dicts may print differently (all tests with Python 3.6.1):

我知道dicts和set不是有序的,所以相同的集合或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}

And I just realized that pprint (“pretty-print”) sorts dicts but not sets:

我刚刚意识到pprint("漂亮的打印")分类而不是集合:

>>> 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.

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

1 个解决方案

#1


4  

This was raised in issue 27495 and it is a bug, rather than just a design choice, but apparently has not yet been resolved.

这是在第27495期提出的,它是一个bug,而不仅仅是一个设计选择,但显然还没有得到解决。

Here is another example from the issue that illustrates perhaps more obviously the behavior you identify in Python 3:

下面是问题中的另一个例子,它可能更明显地说明了您在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:

frozenset()也是如此,但是请注意,多行pprint输出是在Python 3中排序的,例如:

>>> 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:

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

>>> 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.

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

For dicts, a similar example, illustrates as you note, that the output is sorted in either Python 3 or 2, as it should be:

对于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}

However, for Python 3.6, it could be considered surprising that pprint sorts dicts 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 dicts.

然而,对于Python 3.6来说,pprint排序命令是令人惊讶的,因为它们是现在订购的。然而,由于这只是一个实现细节(目前),我认为pprint没有义务维护插入顺序(至今),这样做会破坏pprint自身在Python版本中始终排序句的一致性。

#1


4  

This was raised in issue 27495 and it is a bug, rather than just a design choice, but apparently has not yet been resolved.

这是在第27495期提出的,它是一个bug,而不仅仅是一个设计选择,但显然还没有得到解决。

Here is another example from the issue that illustrates perhaps more obviously the behavior you identify in Python 3:

下面是问题中的另一个例子,它可能更明显地说明了您在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:

frozenset()也是如此,但是请注意,多行pprint输出是在Python 3中排序的,例如:

>>> 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:

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

>>> 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.

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

For dicts, a similar example, illustrates as you note, that the output is sorted in either Python 3 or 2, as it should be:

对于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}

However, for Python 3.6, it could be considered surprising that pprint sorts dicts 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 dicts.

然而,对于Python 3.6来说,pprint排序命令是令人惊讶的,因为它们是现在订购的。然而,由于这只是一个实现细节(目前),我认为pprint没有义务维护插入顺序(至今),这样做会破坏pprint自身在Python版本中始终排序句的一致性。