The sorted(iterable, *, key=None, reverse=False) built-in function builds and returns a new sorted list from the elements of any iterable.
Non-Destructive Timsort: Unlike list.sort() which modifies the source list in place and returns None, sorted() leaves the original iterable untouched and operates on any collection (including tuples, strings, sets, and dictionary keys). It implements the adaptive, stable Timsort algorithm in O(N log N) worst-case time complexity. For reversing sequences without sorting, see reversed(), or filter items conditionally with filter().
The sorted() function accepts one positional iterable and optional keyword arguments:
# Formal syntax of built-in sorted()
sorted_list = sorted(iterable, /, *, key=None, reverse=False)
| Parameter | Type Accepted | Behavioral Details |
|---|---|---|
iterable |
Iterable[T] |
Any iterable sequence or collection (such as list, tuple, string, set, dict keys, or generator). |
key |
Callable or None |
Optional single-argument function (e.g. len, str.lower) extracting a comparison key from each element. Defaults to None. |
reverse |
bool |
Optional boolean flag. If set to True, items are sorted in descending order. Defaults to False. |
| Return Value | list |
Always returns a newly allocated list containing all elements in sorted order. |
Pass any iterable collection to sorted() to generate a new ordered list without modifying the input:
# 1. Sorting a numeric list
numbers = [12, 3, 8, 7, 14]
sorted_nums = sorted(numbers)
print("Sorted copy: ", sorted_nums)
print("Original list:", numbers)
# 2. Sorting strings and characters
fruits = ["Orange", "Banana", "Apple", "Mango"]
print("Sorted fruits: ", sorted(fruits))
text = "plus2net"
print("Sorted letters:", sorted(text))
Output:
Sorted copy: [3, 7, 8, 12, 14]
Original list: [12, 3, 8, 7, 14]
Sorted fruits: ['Apple', 'Banana', 'Mango', 'Orange']
Sorted letters: ['2', 'e', 'l', 'n', 'p', 's', 't', 'u']
Pass reverse=True to arrange items in descending order directly:
# Descending sort using reverse=True
numbers = [12, 3, 8, 7, 14]
descending_nums = sorted(numbers, reverse=True)
print("Descending numbers:", descending_nums)
fruits = ["Orange", "Banana", "Apple", "Mango"]
print("Descending fruits: ", sorted(fruits, reverse=True))
Output:
Descending numbers: [14, 12, 8, 7, 3]
Descending fruits: ['Orange', 'Mango', 'Banana', 'Apple']
The key parameter accepts a callable function computing comparison proxy values:
# 1. Sorting by length using built-in len as key
words = ["Three", "One", "Seven", "thirtyfive", "Two"]
by_length = sorted(words, key=len)
print("Sorted by length:", by_length)
# 2. Case-insensitive sorting with str.lower
mixed_cases = ["banana", "Apple", "orange", "Cherry"]
case_insensitive = sorted(mixed_cases, key=str.lower)
print("Case-insensitive:", case_insensitive)
# 3. Custom key function for tuples
records = [(3, 5), (2, 1), (8, 4), (3, 7)]
def get_second(item):
return item[1]
by_second = sorted(records, key=get_second)
print("Sorted by 2nd item:", by_second)
Output:
Sorted by length: ['One', 'Two', 'Three', 'Seven', 'thirtyfive']
Case-insensitive: ['Apple', 'banana', 'Cherry', 'orange']
Sorted by 2nd item: [(2, 1), (8, 4), (3, 5), (3, 7)]
key function is called exactly once for each input element. This Schwartzian Transform optimization prevents repeated key computations during element comparisons.
Compare non-destructive copying with in-place list mutation:
| Feature | sorted(iterable) |
list.sort() |
|---|---|---|
| Input Scope | Any iterable (tuple, set, dict, string, generator) | Exclusively list instances |
| Modification | Non-destructive (leaves source intact) | In-place mutation (modifies list directly) |
| Return Value | New list instance |
None |
| Memory Overhead | O(N) memory to allocate new list copy | O(1) auxiliary memory (sorts in-place) |
# sorted() creates a new list; list.sort() mutates in-place
original_data = [5, 2, 9, 1]
# sorted() leaves original untouched and returns a new list
result_copy = sorted(original_data)
print("result_copy:", result_copy)
print("original_data:", original_data)
# list.sort() modifies original and returns None
ret_val = original_data.sort()
print("original_data after sort():", original_data)
print("return value of sort(): ", ret_val)
Output:
result_copy: [1, 2, 5, 9]
original_data: [5, 2, 9, 1]
original_data after sort(): [1, 2, 5, 9]
return value of sort(): None
Multi-level comparisons across dictionary fields or custom objects:
# Recipe A: Multi-attribute sorting using operator.itemgetter
from operator import itemgetter
employees = [
{"name": "Alice", "dept": "HR", "salary": 75000},
{"name": "Bob", "dept": "IT", "salary": 92000},
{"name": "Charlie", "dept": "IT", "salary": 85000},
{"name": "Diana", "dept": "HR", "salary": 80000},
]
# Sort by department ascending, then by salary descending
by_dept_salary = sorted(employees, key=lambda e: (e["dept"], -e["salary"]))
for emp in by_dept_salary:
print(f"{emp['dept']} | {emp['salary']} | {emp['name']}")
# Recipe B: Stable sorting with custom object keys
class Student:
def __init__(self, name: str, grade: int, gpa: float):
self.name = name
self.grade = grade
self.gpa = gpa
students = [Student("Amy", 10, 3.8), Student("Ben", 11, 3.9), Student("Cara", 10, 3.95)]
top_students = sorted(students, key=lambda s: s.gpa, reverse=True)
print("Top student:", top_students[0].name, top_students[0].gpa)
Output:
HR | 80000 | Diana
HR | 75000 | Alice
IT | 92000 | Bob
IT | 85000 | Charlie
Top student: Cara 3.95
TypeError: '<' not supported between instances. Provide a custom key=str function if needed.sorted() always yields a list, never a set or string. Use "".join(sorted(text)) or tuple(sorted(t)) when you need the original container type.sorted() copies items quickly into an internal array, modifying the underlying data structure in a concurrent thread can lead to inconsistent state.# Pitfall 1: Sorting unorderable mixed types in Python 3
try:
sorted([10, "apple", 5])
except TypeError as err:
print("Mixed types error:", err)
# Pitfall 2: Sorting sets returns a list, not a set
unique_numbers = {9, 1, 4, 3}
sorted_result = sorted(unique_numbers)
print("Type of sorted result:", type(sorted_result), sorted_result)
Output:
Mixed types error: '<' not supported between instances of 'str' and 'int'
Type of sorted result: [1, 3, 4, 9]
Practice stable sorting, multi-criteria lambdas, and benchmark sorting performance in our companion Jupyter Notebook:
Explore interactive code cells, benchmark sorted() vs list.sort(), implement multi-field dictionary sorting, and run self-validating assertions.
Run these unit checks directly in Python or your local environment to verify sorted() mechanics:
def test_sorted_mechanics():
# 1. Basic sorting
assert sorted([5, 1, 3]) == [1, 3, 5]
assert sorted([5, 1, 3], reverse=True) == [5, 3, 1]
# 2. Key function with length
words = ["bb", "a", "ccc"]
assert sorted(words, key=len) == ["a", "bb", "ccc"]
# 3. Tuple key multi-criteria
data = [(1, "b"), (2, "a"), (1, "a")]
assert sorted(data) == [(1, "a"), (1, "b"), (2, "a")]
# 4. Guaranteeing original iterable immutability
original = [4, 2, 8]
res = sorted(original)
assert original == [4, 2, 8]
assert res == [2, 4, 8]
print("All sorted() unit assertions passed! 100% verified.")
test_sorted_mechanics()
Output:
All sorted() unit assertions passed! 100% verified.
Returns a reverse iterator over sequence elements without creating a reversed copy.
Extracts elements from an iterable matching a boolean predicate condition.
Applies a function to all elements in an iterable, returning a lazy transformation iterator.
Calculates the total number of items in a sequence or collection.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.