Python 3.x's sorted sorted() function cannot be used to sort heterogeneous sequences, since most pairs of different types are unordered (numeric types such as int , float , decimal.Decimal , etc. are decimal.Decimal exceptions):
Python 3.4.2 (default, Oct 8 2014, 08:07:42) [GCC 4.8.2] on linux Type "help", "copyright", "credits" or "license" for more information. >>> sorted(["one", 2.3, "four", -5]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unorderable types: float() < str()
In contrast, comparisons between objects that do not have a natural order are arbitrary but consistent in Python 2.x, so sorted() works:
Python 2.7.8 (default, Aug 8 2014, 14:55:30) [GCC 4.8.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> sorted(["one", 2.3, "four", -5]) [-5, 2.3, 'four', 'one']
To replicate the behavior of Python 2.x in Python 3.x, I wrote a class to use as the key parameter for sorted() , which is based on the fact that sorted() guaranteed to use only less than comparisons:
class motley: def __init__(self, value): self.value = value def __lt__(self, other): try: return self.value < other.value except TypeError: return repr(type(self.value)) < repr(type(other.value))
Usage example:
>>> sorted(["one", 2.3, "four", -5], key=motley) [-5, 2.3, 'four', 'one']
So far, so good.
However, I noticed an amazing behavior when sorted(s, key=motley) is called with specific sequences containing complex numbers:
>>> sorted([0.0, 1, (1+0j), False, (2+3j)], key=motley) [(1+0j), 0.0, False, (2+3j), 1]
I would expect that 0.0 , False and 1 would be in one group (because they are mutually ordered), and (1+0j) and (2+3j) in another (because they are of the same type). The fact that complex numbers in this result are not only separated from each other, but also one of them is in the middle of a group of objects that are comparable with each other, but not with it, is somewhat puzzling.
What's going on here?