Sort Lists
Learn how to sort Python lists with sorted() and sort(), use the key parameter, sort in reverse, and handle custom objects with clear examples.
Sorting a list is one of the most common operations in Python. Python gives you two built-in tools for this: the sorted() function, which returns a new sorted list without changing the original, and the list.sort() method, which reorders the list in place. Both accept a reverse flag for descending order and a key parameter for custom sort logic.
This chapter covers:
sorted()— sort any iterable into a new listlist.sort()— sort a list in place- Sorting in ascending and descending order
- The
keyparameter — sort by length, field, or any custom criterion - Case-insensitive sorting
- Sorting lists of dictionaries and custom objects
- Multi-key sorting
operator.itemgetteras an efficient alternative to lambda
For a refresher on list fundamentals, see the Python Lists and List Methods chapters.
The sorted() Function
sorted() takes any iterable (list, tuple, string, …) and returns a new sorted list. The original iterable is left unchanged.
Syntax:
sorted(iterable, *, key=None, reverse=False)iterable— the sequence to sortkey— an optional one-argument function applied to each element before comparing (default: compare elements directly)reverse— set toTrueto sort in descending order (default:False)
Sort a list of strings
Sort a list of numbers
Numeric lists sort by magnitude, not by string representation (so 10 does not sort before 9).
nums = [3, 1, 4, 1, 5, 9, 2, 6]
print(sorted(nums))
# [1, 1, 2, 3, 4, 5, 6, 9]Sort in descending order with reverse=True
Pass reverse=True to get the largest values first.
nums = [3, 1, 4, 1, 5, 9, 2, 6]
print(sorted(nums, reverse=True))
# [9, 6, 5, 4, 3, 2, 1, 1]The list.sort() Method
list.sort() reorders the list in place and always returns None. Use it when you no longer need the original order and want to avoid the memory overhead of a second list.
Syntax:
list.sort(*, key=None, reverse=False)The parameters are identical to sorted().
Sort a list in place
Sort in descending order
sort() returns None — a common pitfall
A frequent mistake is assigning the result of sort() to a variable:
fruits = ['banana', 'apple', 'cherry']
result = fruits.sort() # sort() modifies fruits, returns None
print(result) # None ← not the sorted list!
print(fruits) # ['apple', 'banana', 'cherry'] ← fruits was modifiedIf you need both the sorted result and the original order, use sorted() instead.
sorted() vs list.sort() — When to Use Which
sorted() | list.sort() | |
|---|---|---|
| Returns | A new sorted list | None |
| Original list | Unchanged | Modified in place |
| Works on | Any iterable | Lists only |
| Memory | Uses extra memory | No extra list |
Use sorted() when you need the original unchanged, or when sorting a tuple or other iterable.
Use list.sort() when you have a list, you want to sort it in place, and memory efficiency matters.
Sorting with the key Parameter
The key parameter accepts a one-argument callable. Python calls it once on each element and uses the returned value for comparisons. This avoids duplicating data and makes sorting flexible.
Sort by string length
words = ['banana', 'apple', 'cherry', 'kiwi']
print(sorted(words, key=len))
# ['kiwi', 'apple', 'banana', 'cherry']len is passed directly — no lambda needed when using a built-in function that takes one argument.
Sort a list of tuples by a specific field
The lambda lambda x: x[1] extracts the second element (the number) from each tuple so Python compares numbers instead of whole tuples.
Sort a list of dictionaries
students = [
{'name': 'Charlie', 'grade': 85},
{'name': 'Alice', 'grade': 92},
{'name': 'Bob', 'grade': 78},
]
by_grade = sorted(students, key=lambda s: s['grade'])
for s in by_grade:
print(s['name'], s['grade'])
# Bob 78
# Charlie 85
# Alice 92To sort in descending order (highest grade first), add reverse=True:
by_grade_desc = sorted(students, key=lambda s: s['grade'], reverse=True)
for s in by_grade_desc:
print(s['name'], s['grade'])
# Alice 92
# Charlie 85
# Bob 78Case-insensitive sorting
By default, Python's sort is case-sensitive: all uppercase letters come before lowercase letters because they have lower Unicode code points. Use key=str.lower to sort without regard to case.
words = ['Banana', 'apple', 'Cherry', 'date']
print(sorted(words)) # case-sensitive (uppercase first)
# ['Banana', 'Cherry', 'apple', 'date']
print(sorted(words, key=str.lower)) # case-insensitive
# ['apple', 'Banana', 'Cherry', 'date']Using operator.itemgetter and operator.attrgetter
The operator module provides faster alternatives to lambda for common key patterns.
operator.itemgetter — for sequences and dicts
import operator
fruits = [('apple', 10), ('banana', 5), ('cherry', 20)]
print(sorted(fruits, key=operator.itemgetter(1)))
# [('banana', 5), ('apple', 10), ('cherry', 20)]operator.itemgetter(1) is equivalent to lambda x: x[1] but is implemented in C and runs faster on large lists.
operator.attrgetter — for objects
import operator
class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade
def __repr__(self):
return f'Student({self.name!r}, {self.grade})'
students = [Student('Charlie', 85), Student('Alice', 92), Student('Bob', 78)]
print(sorted(students, key=operator.attrgetter('grade')))
# [Student('Bob', 78), Student('Charlie', 85), Student('Alice', 92)]Multi-Key Sorting
Return a tuple from the key function to sort by multiple criteria. Python compares tuples element-by-element, so ties on the first key fall through to the second.
# Sort by grade ascending, then by name alphabetically when grades tie
data = [('Alice', 85), ('Bob', 92), ('Charlie', 85), ('Dave', 78)]
result = sorted(data, key=lambda x: (x[1], x[0]))
print(result)
# [('Dave', 78), ('Alice', 85), ('Charlie', 85), ('Bob', 92)]Alice and Charlie both have grade 85, so they are sorted alphabetically — Alice before Charlie.
Sort Stability
Python's sort is stable: elements that compare equal keep their original relative order. This means you can sort a list by one key, then sort the result by another key, and the first sort's order is preserved within ties of the second key.
# Sort by grade, then (stably) by name — same result as the tuple key above
data = [('Alice', 85), ('Bob', 92), ('Charlie', 85), ('Dave', 78)]
step1 = sorted(data, key=lambda x: x[0]) # sort by name first
step2 = sorted(step1, key=lambda x: x[1]) # then sort by grade
print(step2)
# [('Dave', 78), ('Alice', 85), ('Charlie', 85), ('Bob', 92)]This technique — called a Schwartzian transform — is sometimes more readable than a composite key.
Conclusion
Python's sorted() and list.sort() give you fast, flexible list sorting with minimal code. Use sorted() when you need a new list or are sorting a non-list iterable; use list.sort() when you want to modify a list in place. The key parameter handles almost any sorting criterion — from sorting by length or a dict field to case-insensitive comparisons. For large datasets, prefer operator.itemgetter or operator.attrgetter over lambda for better performance.
Related reading:
- Python Lists — list creation, indexing, and slicing
- List Methods — full reference for list methods
- List Comprehension — concise list construction
- Loop Lists — iterating over lists