New submission from Nick Coghlan: Armin Ronacher pointed out that one downside of the removal of implicit cross-type comparisons in Python 3 is that it makes it harder to produce a stable repr for mixed-type containers.
This seems like a valid point to me, so I propose adding a suitable "MixedTypeKey" definition to reprlib. Passing "key=reprlib.MixedTypeKey" would then reproduce the old Python 2. sorting behaviour. We can actually improve on the Python 2 approach by basing the fallback comparison on fully qualified type names rather than on the type id. Proposed implementation (see https://gist.github.com/ncoghlan/5743523): >>> class MixedTypeKey: ... """Sort key for mixed type lists in Python 3 ... ... >>> sorted([None, ..., 1, 1j, "", (), {}, []]) ... Traceback (most recent call last): ... File "<stdin>", line 1, in <module> ... TypeError: unorderable types: ellipsis() < NoneType() ... >>> sorted([None, ..., 1, 1j, "", (), {}, []], key=MixedTypeKey) ... [None, Ellipsis, 1, 1j, '', (), {}, []] ... """ ... def __init__(self, k): ... self._sort_key = k ... self._type_name = self._get_fully_qualified_name(k) ... def _get_fully_qualified_name(self, k): ... k_type = type(k) ... # Use __qualname__ if available, __name__ otherwise ... try: ... k_name = k_type.__qualname__ ... except AttributeError: ... k_name = k_type.__name__ ... return k_type.__module__ + "." + k_name ... def __lt__(self, other): ... # Try standard sorting first ... sort_key = self._sort_key ... try: ... other_sort_key = other._sort_key ... except AttributeError: ... other_sort_key = other ... try: ... return sort_key < other_sort_key ... except TypeError: ... pass ... # If that fails, sort by the fully qualified type names ... try: ... other_type_name = other._type_name ... except AttributeError: ... other_type_name = self._get_fully_qualified_name(other) ... return self._type_name < other_type_name ... >>> sorted([None, ..., 1, 1j, "", (), {}, []]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unorderable types: ellipsis() < NoneType() >>> sorted([None, ..., 1, 1j, "", (), {}, []], key=MixedTypeKey) [None, 1j, {}, Ellipsis, 1, [], '', ()] >>> MixedTypeKey(None) < ... True The stdlib version could omit the fallback to __name__ (since it doesn't need to cope with old versions of Python) Support for other comparisons could theoretically be added, but I advise against it without a solid use case (sorting only needs __lt__). ---------- components: Library (Lib) messages: 190855 nosy: ncoghlan priority: normal severity: normal stage: needs patch status: open title: Add MixedTypeKey to reprlib type: enhancement versions: Python 3.4 _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue18173> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com