sorted() vs .sort() in Python

โฑ๏ธ 40 sec read ๐Ÿ Python

sorted() returns a new sorted list and works on any iterable, while list.sort() sorts a list in place and returns None. Use sorted() by default; use .sort() only when you own the list and want to avoid a copy.

What Is the Difference Between sorted() and .sort()?

.sort() mutates the original list and hands back nothing, which is the classic trap: assigning its result gives you None. sorted() leaves the input untouched and accepts tuples, dicts, sets, and generators too.

nums = [3, 1, 2]

result = sorted(nums)   # [1, 2, 3], nums unchanged
nums.sort()             # nums is now [1, 2, 3]

bad = nums.sort()       # bad is None โ€” common bug!

sorted({"b": 2, "a": 1})        # ['a', 'b'] โ€” sorts dict keys
sorted((3, 1, 2))               # [1, 2, 3] โ€” tuple in, list out

How Does the key Parameter Work?

key= takes a function that is called once per element, and elements are ordered by what it returns. Lambdas handle one-off logic; operator.itemgetter and attrgetter are cleaner and faster for field access.

from operator import itemgetter

words = ["banana", "Fig", "apple"]
sorted(words, key=str.lower)          # ['apple', 'banana', 'Fig']

rows = [("bob", 82), ("alice", 91), ("cara", 78)]
sorted(rows, key=lambda r: r[1])      # sort by score
sorted(rows, key=itemgetter(1))       # same, idiomatic

New to the lambda syntax? See lambda functions in Python.

What Does reverse=True Do?

reverse=True flips the order to descending โ€” both functions accept it, and it keeps the sort stable, unlike negating values or reversing afterward in some edge cases.

sorted([3, 1, 2], reverse=True)              # [3, 2, 1]
sorted(rows, key=itemgetter(1), reverse=True)
# [('alice', 91), ('bob', 82), ('cara', 78)]

How Do You Sort by Multiple Keys?

Two ways: return a tuple from key= for same-direction sorts, or exploit the fact that Python's sort is stable (ties keep their previous order) and sort in passes from least to most significant key.

staff = [("sales", "bob", 50), ("eng", "amy", 70), ("sales", "amy", 60)]

# Tuple key โ€” dept ascending, then salary ascending:
sorted(staff, key=lambda s: (s[0], s[2]))

# Mixed directions โ€” salary DESC within dept ASC:
staff.sort(key=itemgetter(2), reverse=True)   # secondary key first
staff.sort(key=itemgetter(0))                 # primary key last
# [('eng', 'amy', 70), ('sales', 'amy', 60), ('sales', 'bob', 50)]

The multi-pass trick works precisely because stability guarantees the salary ordering survives the department sort.

Common Pitfalls

Pro Tip: To sort a dict by value, combine sorted with items(): dict(sorted(d.items(), key=itemgetter(1), reverse=True)) โ€” since Python 3.7 the rebuilt dict keeps that insertion order.

โ† Back to Python Tips