Python: list.sort() query when list contains different element types

Viewed 15452

Greetings Pythonic world. Day 4 of learning Python 3.3 and I've come across a strange property of list.sort.

I created a list of five elements: four strings, with a number in the middle. Trying to get list.sort to work gave the expected error because of mixing types:

>>> list = ['b', 'a', 3, 'd', 'c']
>>> list.sort()
Traceback (innermost last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < str()
>>> list
['b', 'a', 3, 'd', 'c']

The list is unchanged.

But then I moved the number to the end, used list.sort again, and got this:

>>> list = ['b', 'a', 'd', 'c', 3]
>>> list.sort()
Traceback (innermost last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < str()
>>> list
['a', 'b', 'c', 'd', 3]

OK, an error. But the list has sorted itself, kicking the number to the end. I couldn't find any explanation for this on this site or in Langtangen. Is there some underlying reason for this behaviour? Would it be useful in some situation?

5 Answers

I came up with the same problem recently, and didn't wanted to cast everything to a string, so I did this, hope it helps :)

list = ["a", 1, False, None, "b", (1,3), (1, 'a'),(1, [None, False]), True, 3, False]

type_weights = {}
for element in list:
    if type(element) not in type_weights:
        type_weights[type(element)] = len(type_weights)

print(sorted(list, key=lambda element: (type_weights[type(element)], str(element))))

It should return something like this: ['a', 'b', 1, 3, False, False, True, None, (1, 'a'), (1, 3), (1, [None, False])]

It should work with any data type (including custom classes)

Related