Sorting in Python: key, reverse, and Sorting by More Than One Field

Last edited Oct 19, 2026 · 4 min read

sorted(items, key=...) is how you sort anything by something other than its default order: by length, by the second item of a pair, by a dictionary value. The key argument is a function that Python calls on each item to get the value to compare. Every example below was run in Python 3.13 and the output shown is what it printed.

1. The two ways to sort

The official sorting guide describes both. sorted() builds a new sorted list from any iterable and leaves the original alone. list.sort() changes the list in place and returns None, and it only exists for lists.

nums = [5, 2, 9, 1]
result = nums.sort()
print(result, nums)
None [1, 2, 5, 9]

result is None because sort() modifies the list and returns nothing. Writing nums = nums.sort() throws your list away.

2. Changing the comparison with key

The guide says key takes a function (or other callable) that receives one item and returns the value to sort by, and that Python calls it exactly once per item. A plain sort of mixed-case words puts capitalized words first:

words = "banana Cherry apple date Elderberry fig".split()
print(sorted(words))
print(sorted(words, key=str.casefold))
print(sorted(words, key=len))
['Cherry', 'Elderberry', 'apple', 'banana', 'date', 'fig']
['apple', 'banana', 'Cherry', 'date', 'Elderberry', 'fig']
['fig', 'date', 'apple', 'banana', 'Cherry', 'Elderberry']

The second line uses str.casefold, the same case-insensitive trick the guide demonstrates. The third sorts by length. Notice that you pass the function itself (len), not a call (len(...)). banana and Cherry both have 6 letters, and they stay in their original order, which is the next topic.

3. reverse=True and stability

Both sorted() and list.sort() accept reverse=True for a descending sort.

print(sorted(words, key=len, reverse=True))
print(words)
['Elderberry', 'banana', 'Cherry', 'apple', 'date', 'fig']
['banana', 'Cherry', 'apple', 'date', 'Elderberry', 'fig']

The original list is unchanged. Also, banana still comes before Cherry. The guide states that sorts are guaranteed to be stable: records with equal keys keep their original order, and reverse keeps that property too. So reverse=True does not simply flip the whole output.

4. Sorting records by a field

With tuples, use a small lambda to pick the field. Take four orders as (name, status, amount):

orders = [
    ("Ana", "pending", 30),
    ("Ben", "shipped", 12),
    ("Cy", "pending", 12),
    ("Dee", "shipped", 45),
]
print(sorted(orders, key=lambda o: o[2]))
[('Ben', 'shipped', 12), ('Cy', 'pending', 12), ('Ana', 'pending', 30), ('Dee', 'shipped', 45)]

Ben and Cy both have an amount of 12, and Ben stays first because he was first in the input. That is stability at work.

5. Sorting by two fields

To sort by status, then by amount inside each status, return a tuple from the key. Python compares tuples item by item.

print(sorted(orders, key=lambda o: (o[1], o[2])))
[('Cy', 'pending', 12), ('Ana', 'pending', 30), ('Ben', 'shipped', 12), ('Dee', 'shipped', 45)]

The guide also shows itemgetter from the operator module as a shorter, faster way to write the same thing:

from operator import itemgetter
print(sorted(orders, key=itemgetter(1, 2)))
[('Cy', 'pending', 12), ('Ana', 'pending', 30), ('Ben', 'shipped', 12), ('Dee', 'shipped', 45)]

The output matches the lambda version.

6. Mixed directions: sort twice

What if status should go A to Z but amount should go high to low? A tuple key cannot do that with plain numbers and text together, but stability can. The guide notes that stability lets you build complex sorts in steps. Sort by the least important field first, then by the most important:

step1 = sorted(orders, key=itemgetter(2), reverse=True)
step2 = sorted(step1, key=itemgetter(1))
print(step2)
[('Ana', 'pending', 30), ('Cy', 'pending', 12), ('Dee', 'shipped', 45), ('Ben', 'shipped', 12)]

The first pass orders by amount, high to low. The second pass groups by status, and because it is stable, each group keeps the amount order from the first pass.

7. Sorting a dictionary

Sorting a dictionary gives you its keys. To order by value, pass the lookup as the key:

scores = {"mia": 82, "leo": 91, "zed": 75}
print(sorted(scores))
print(sorted(scores, key=scores.get, reverse=True))
print(sorted(scores.items(), key=lambda kv: kv[1]))
['leo', 'mia', 'zed']
['leo', 'mia', 'zed']
[('zed', 75), ('mia', 82), ('leo', 91)]

The first two lines look identical here only because the names happen to be alphabetical in the same order as the scores, high to low. The third sorts the (name, score) pairs by score, lowest first.

8. Two common surprises

Text that looks like numbers sorts as text:

print(sorted(["10", "9", "2"]))
print(sorted(["10", "9", "2"], key=int))
['10', '2', '9']
['2', '9', '10']

Passing key=int converts each string to a number for the comparison only; the items stay strings. And mixing types that cannot be compared fails:

sorted([3, "a", 1])
TypeError: '<' not supported between instances of 'str' and 'int'

9. Key takeaways

  • sorted() returns a new list; list.sort() changes the list and returns None.
  • key is a function called once per item that returns the value to compare. Pass len, not len(...).
  • reverse=True gives a descending sort and still keeps equal items in their original order.
  • Return a tuple from the key, or use itemgetter, to sort by several fields.
  • Because Python sorts are stable, you can sort in passes, least important field first, to mix ascending and descending.
  • Strings that look like numbers sort as text unless you use key=int.

Sources

  1. Python Software Foundation, Sorting Techniques (HOWTO)
  2. Python Software Foundation, Built-in Functions, sorted()
CategoriesCoding From Zeropythonsortinglistsbeginners

More on work & tech from other topics