How to sort in python

There are two built-in ways to sort in python: the .sort method or the built-in global sorted function.

The .sort method is specific to lists - invoking it on anything other than a list will trigger an attribute error. The sorted function, however, can accept any iterable as input (lists, strings, dictionaries).

Here’s a high level breakdown of the similarities and differences (I put the differences first):

Attribute.sortsorted
Sorts any iterableNo - list onlyYes
In-placeYesNo
Return valueNonea new list
StableYesYes
Default sort orderAscendingAscending
Time complexityO(n log n)O(n log n)
Space complexityO(n)O(n)

Examples

The .sort method on a simple list:

>>> numbers = [3, 2, 1]
>>> numbers.sort()
>>> numbers
[1, 2, 3]

Try calling .sort on an iterable other than a list:

>>> letters = 'cba'
>>> letters.sort()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'sort'

Woops, not supported.

Calling sorted on strings and lists:

>>> sorted([3, 2, 1])
[1, 2, 3]
>>> sorted("cba")
['a', 'b', 'c']

sorted will always return a new list. By the way, dictionaries and sets are also iterables so you can sort them too (you’ll just get back the keys though).

>>> sorted({"c": 1, "b": 2, "a": 3})
['a', 'b', 'c']
>>> sorted({"c", "b", "a"})
['a', 'b', 'c']

Note: dictionaries since python 3.7 preserve the insertion order of keys. By default, calling sorted on a dictionary, as you see above, sorts by keys.

Sorting with a key function

You need to provide a key function if you’re sorting a list of dictionaries or any object that does not support > or < operators.

With .sort:

>>> objects.sort(key=lambda x: x["x"])
>>> objects
[{'x': 1}, {'x': 2}, {'x': 3}]

With sorted:

>>> sorted(objects, key=lambda x: x["x"])
[{'x': 1}, {'x': 2}, {'x': 3}]

Sorting in reverse

Elements are sorted in ascending order, smallest value first, by default. Pass reverse=True to sort by largest value first.

With .sort:

>>> numbers = [2, 1, 3]
>>> numbers.sort(reverse=True)
>>> numbers
[3, 2, 1]

With sorted:

>>> numbers = [2, 1, 3]
>>> sorted(numbers, reverse=True)
[3, 2, 1]

In general, I recommend using sorted unless you absolutely need an in-place sort.