[New-bugs-announce] [issue22721] pprint output for sets and dicts is not stable

Serhiy Storchaka report at bugs.python.org
Fri Oct 24 19:00:50 CEST 2014

New submission from Serhiy Storchaka:

pprint() sorts the content of sets and dicts in order to get stable output which doesn't depend on iteration order of set or dict, which depend not only from values of elements, but also from set or dict history.

But in some cases the output is different for equal sets or dicts which differs only by their history.

>>> import pprint
>>> class A:  # string 'A' < 'int'
...     def __lt__(self, other): return False
...     def __gt__(self, other): return self != other
...     def __le__(self, other): return self == other
...     def __ge__(self, other): return True
...     def __eq__(self, other): return self is other
...     def __ne__(self, other): return self is not other
...     def __hash__(self): return 1  # == hash(1)
>>> a = A()
>>> sorted([1, a])
[1, <__main__.A object at 0xb700c64c>]
>>> sorted([a, 1])
[1, <__main__.A object at 0xb700c64c>]
>>> # set
>>> pprint.pprint({1, a})
{<__main__.A object at 0xb700c64c>, 1}
>>> pprint.pprint({a, 1})
{1, <__main__.A object at 0xb700c64c>}
>>> # dict
>>> pprint.pprint({1: 1, a: 1})
{1: 1, <__main__.A object at 0xb700c64c>: 1}
>>> pprint.pprint({a: 1, 1: 1})
{<__main__.A object at 0xb700c64c>: 1, 1: 1}

This is happen because _safe_key's __lt__() calls the __lt__() method of it's left argument, and doesn't use special methods of it's right argument. a.__lt__(1) is successful, but (1).__lt__(a) is failed.

I think that instead of `self.obj.__lt__(other.obj)` here should be `self.obj < other.obj`. Or may be call other.obj.__gt__(self.obj) if the result of self.obj.__lt__(other.obj) is NotImplemented.

_safe_key was introduced in issue3976.

components: Library (Lib)
messages: 229943
nosy: fdrake, rhettinger, serhiy.storchaka
priority: normal
severity: normal
status: open
title: pprint output for sets and dicts is not stable
type: behavior
versions: Python 3.4, Python 3.5

Python tracker <report at bugs.python.org>

More information about the New-bugs-announce mailing list