Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pprint sorting dicts but not sets?

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.

like image 529
Stefan Pochmann Avatar asked Jul 10 '17 15:07

Stefan Pochmann


People also ask

Does Pprint sort?

Using pprintThe Python pprint module actually already sorts dictionaries by key. The pprint module provides a capability to “pretty-print” arbitrary Python data structures in a form which can be used as input to the interpreter.

How do I enable Pprint?

To use pprint, begin by importing the library at the top of your Python file. From here you can either use the . pprint() method or instantiate your own pprint object with PrettyPrinter() .


1 Answers

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

like image 102
Chris_Rands Avatar answered Sep 25 '22 00:09

Chris_Rands