Sorting is a routine programming task: you may need to rank scores, arrange names, organize records by date, or display products by price. Python provides two closely related tools—list.sort() and sorted()—and understanding their differences prevents accidental data changes and unnecessary copies.
This guide explains Python sort vs sorted with practical examples, custom keys, reverse ordering, multiple fields, and common mistakes. It builds on the list concepts covered in our Python lists guide.
The essential difference
The sort() method belongs to list objects. It changes that list in place and returns None. The built-in sorted() function accepts any iterable and returns a new list, leaving the original iterable unchanged.
numbers = [8, 3, 12, 1]
numbers.sort()
print(numbers) # [1, 3, 8, 12]numbers = [8, 3, 12, 1]
ordered = sorted(numbers)
print(numbers) # [8, 3, 12, 1]
print(ordered) # [1, 3, 8, 12]The official Python documentation for sorted() describes the function as producing a new sorted list from an iterable. That behavior is useful whenever the original order still has meaning.
When to use list.sort()
Choose sort() when you own a list, no longer need its old order, and want to avoid creating a second list. This is common in local data-processing steps where the list is prepared once and then consumed.
scores = [72, 91, 84, 68, 95]
scores.sort(reverse=True)
top_three = scores[:3]
print(top_three)Because the operation mutates the list, every reference to that same list observes the new order. That can be helpful or surprising, depending on your design.
original = ["pear", "apple", "orange"]
alias = original
original.sort()
print(alias) # The alias sees the sorted order tooIf other parts of a program depend on the original sequence, use sorted() or make an explicit copy first. The article on Python slicing explains the common items[:] copy pattern.
When to use sorted()
Use sorted() when the input is a tuple, set, generator, dictionary view, or another iterable; when you need both original and sorted versions; or when a function should avoid modifying data received from its caller.
coordinates = (4, 1, 9, 2)
ordered = sorted(coordinates)
print(type(ordered).__name__) # list
print(coordinates) # original tuple unchangedA set does not preserve a useful sorted order, but sorted() converts its unique values into an ordered list.
tags = {"python", "data", "api", "testing"}
print(sorted(tags))Descending order with reverse
Both tools accept reverse=True. Python still performs a stable sort; it simply produces the opposite ordering.
prices = [19.90, 5.50, 42.00, 12.75]
low_to_high = sorted(prices)
high_to_low = sorted(prices, reverse=True)
print(low_to_high)
print(high_to_low)Sort with a key function
The key argument tells Python which value to compare for each item. The original items remain in the result; the key is computed only for ordering. This is cleaner than transforming the data manually.
names = ["Ada", "grace", "ALAN", "Guido"]
case_insensitive = sorted(names, key=str.casefold)
print(case_insensitive)Using str.casefold creates a robust case-insensitive comparison for international text.
Sort strings by length
languages = ["Python", "C", "JavaScript", "Go"]
languages.sort(key=len)
print(languages)Sort dictionaries by one field
students = [
{"name": "Maya", "score": 88},
{"name": "Noah", "score": 94},
{"name": "Liam", "score": 88},
]
ranked = sorted(students, key=lambda student: student["score"], reverse=True)
for student in ranked:
print(student["name"], student["score"])A small lambda function is appropriate when the key expression is short. For repeated logic, define a named function so tests and error messages are clearer.
Sort by multiple fields
Tuples are compared from left to right, which makes them ideal as compound sort keys. The next example orders by descending score and then alphabetically by name.
students = [
{"name": "Maya", "score": 88},
{"name": "Noah", "score": 94},
{"name": "Liam", "score": 88},
]
ranked = sorted(
students,
key=lambda student: (-student["score"], student["name"].casefold()),
)
print(ranked)Negating a numeric field reverses that component while leaving the name ascending. For more complex records, operator.itemgetter and operator.attrgetter can make intent explicit.
from operator import itemgetter
products = [
{"category": "books", "price": 20},
{"category": "games", "price": 40},
{"category": "books", "price": 15},
]
products.sort(key=itemgetter("category", "price"))
print(products)Python sorting is stable
A stable sort preserves the relative order of items whose keys compare equal. This allows multi-stage sorting and makes results predictable. In the student example, two equal scores can keep their prior name order if that order was established first.
records = [
("west", 3),
("east", 1),
("west", 1),
("east", 3),
]
records.sort(key=lambda item: item[1])
records.sort(key=lambda item: item[0])
print(records)In many cases a single tuple key is simpler, but stability is valuable when the secondary order already exists or is generated elsewhere.
Handling None and mixed data
Python 3 does not invent an ordering between unrelated types such as integers and strings. Normalize data before sorting. If a field may be None, the key can explicitly place missing values at the end.
values = [10, None, 4, None, 7]
ordered = sorted(
values,
key=lambda value: (value is None, value if value is not None else 0),
)
print(ordered)For user-provided data, validate types early. The guides to Python data types and exception handling provide useful background.
Performance and memory
Both approaches use Python’s highly optimized sorting implementation and have the same general time complexity. The practical memory difference is that sorted() creates a new list, while sort() reorders an existing list. For ordinary application data, choose based on clarity and mutation semantics before chasing small performance differences.
Common mistakes
- Assigning
result = items.sort()and receivingNone. - Using
sort()when another part of the program needs the original order. - Expecting
sorted()to return the same collection type. - Sorting numeric strings without converting them, which places
"10"before"2". - Writing a key function with side effects or expensive repeated work.
- Trying to compare incompatible types without normalization.
A practical inventory example
inventory = [
{"name": "Monitor", "stock": 4, "price": 210.00},
{"name": "Mouse", "stock": 12, "price": 25.00},
{"name": "Keyboard", "stock": 4, "price": 75.00},
]
ordered = sorted(
inventory,
key=lambda item: (item["stock"], item["price"]),
)
for item in ordered:
print(f'{item["name"]}: {item["stock"]} units, ${item["price"]:.2f}')This orders low-stock items first and uses price to break ties. You could adapt the key for sales reports, task priorities, or API results. Combining sorted records with enumerate() is useful for numbered rankings.
Frequently asked questions
Does sort() work on tuples?
No. Tuples do not have a sort() method because they are immutable. Use sorted(tuple_value), which returns a list, and convert back to a tuple only if the result truly needs to be immutable.
Can I sort a dictionary?
Calling sorted(dictionary) sorts its keys. To sort by values or key-value pairs, pass dictionary.items() and provide an appropriate key function.
Which option is better?
Neither is universally better. Use sort() when intentional in-place mutation is clear and safe. Use sorted() when you need a new list, accept any iterable, or want a function to preserve its input.
Final thoughts
The central rule is simple: sort() changes a list and returns None; sorted() returns a new list from any iterable. Once you add key, reverse, tuple keys, and stable ordering, these two tools can handle nearly every everyday sorting task in clean, readable Python.






