Python sorted lambda: Custom Sorting with Key Functions
Learn how to use python sorted lambda to sort lists, dicts, and objects by custom keys, including multiple keys, reverse, and performance considerations.
The sorted() function in Python accepts a key parameter that lets you control the sort order without modifying the original data. When the key logic is short, a lambda function is often the most direct way to express it. This article covers how python sorted lambda works, where it fits, and where a named function or operator helper is better.
How sorted() Uses the key Parameter
The sorted() built-in returns a new list containing all items from an iterable in ascending order. Without a key function, it compares elements directly using their natural order. With key, it calls the function on each element and sorts by the returned value:
numbers = [3, 1, 2] print(sorted(numbers)) # [1, 2, 3] print(sorted(numbers, key=lambda x: -x)) # [3, 2, 1]
The key function is applied once per element, and the original elements remain unchanged. This is the foundation of python sorted lambda: you supply a small anonymous function that extracts the value you want to sort by.
Writing a Lambda for a Single Sort Key
A lambda is a concise way to define a key function inline. For a list of tuples, you might sort by the second element:
pairs = [('b', 2), ('a', 3), ('c', 1)] sorted_pairs = sorted(pairs, key=lambda pair: pair[1]) print(sorted_pairs) # [('c', 1), ('b', 2), ('a', 3)]
For a list of dictionaries, you can sort by a specific field:
records = [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}] sorted_records = sorted(records, key=lambda r: r['age']) print(sorted_records)
The lambda receives each element and returns the sort key. This pattern works for any object with attributes or indexing.
Sorting by Multiple Keys
When you need to sort by several fields, the key function can return a tuple. Python compares tuples element by element:
employees = [ {'name': 'Alice', 'department': 'Eng', 'salary': 90000}, {'name': 'Bob', 'department': 'Eng', 'salary': 80000}, {'name': 'Carol', 'department': 'Sales', 'salary': 85000}, ] sorted_employees = sorted( employees, key=lambda e: (e['department'], e['salary']) )
This sorts by department first, then by salary within each department. To reverse only one field, you can negate numeric values or use a custom comparator, but for strings you often need a different approach.
Combining Lambda with reverse and Stability
The reverse parameter reverses the final order. Because Python's sort is stable, two elements with equal keys keep their original relative order. This matters when you sort in multiple passes:
data = [('a', 2), ('b', 1), ('c', 2)] # Sort by second element, then reverse the whole list sorted_data = sorted(data, key=lambda x: x[1], reverse=True) print(sorted_data) # [('a', 2), ('c', 2), ('b', 1)]
Stability also lets you sort by one key and then another, preserving the first sort's order for ties. For example, sort by name, then by age using two calls.
Performance Considerations for key Functions
The key function is called exactly once per element, so the overhead of a lambda is small. However, if the key function does expensive work—like a database lookup or a complex calculation—that cost is paid for every element. In such cases, precompute the keys once and sort the resulting pairs, or use a named function that can be cached.
A common misconception is that key is called repeatedly during comparisons. That is not true; Python computes all keys upfront. This makes key-based sorting more efficient than a comparator-based approach, which would call the comparison function many times.
Common Mistakes When Using Lambda in sorted()
One frequent mistake is forgetting the key parameter and trying to pass a lambda as the second positional argument, which is the reverse flag. Another is writing a lambda that returns None for some elements, which causes a TypeError during comparison. Also, be careful with side effects: the lambda should be pure and not modify the elements or external state, because the order of calls is not guaranteed.
If you need to sort by an attribute that may be missing, use a default value in the lambda, such as lambda x: x.get('age', 0) for dictionaries.
Alternatives to Lambda: operator.itemgetter and attrgetter
For simple indexing or attribute access, operator.itemgetter and operator.attrgetter are faster and more readable than a lambda. They are implemented in C and avoid the overhead of a Python function call:
from operator import itemgetter pairs = [('b', 2), ('a', 3), ('c', 1)] sorted_pairs = sorted(pairs, key=itemgetter(1))
For multiple keys, pass multiple arguments to itemgetter:
sorted_employees = sorted(employees, key=itemgetter('department', 'salary'))
This is often the better choice when the key is a simple field access. Use a lambda when you need to transform the value, such as converting to lowercase or applying arithmetic.
When Lambda Is the Right Choice
Use python sorted lambda when the key logic is short, specific to one call, and not reused elsewhere. If the same key function appears in multiple sorts, define a named function to avoid duplication. If the key is a direct attribute or index, prefer operator.itemgetter or attrgetter for clarity and speed. If the key requires computation that is expensive, consider precomputing the keys in a separate structure.
The lambda is a tool, not a rule. Choose the approach that makes the sorting logic easiest to read and maintain in your specific context.