PYTHON • COLLECTIONS AND STRINGS

Sorting with Key Functions — Sort with sorted() and list.sort(); use key functions (intro)

Master Python's powerful sorting tools and learn how key functions let you sort data any way you want.

Historical Context & Motivation

Sorting is one of the most fundamental operations in computer science. Every time you organize a playlist alphabetically, rank scores from highest to lowest, or filter search results by relevance, a sorting algorithm is doing the heavy lifting behind the scenes. Early programming languages forced developers to write their own sorting code from scratch, which was error-prone and time-consuming.

Python's designers recognized that sorting was so common that it deserved built-in, optimized tools. Over time, Python evolved its sorting capabilities from basic comparison-based methods to the elegant key function approach we use today. This lets you tell Python how to compare items, rather than writing the comparison logic yourself.

1991
Python 1.0 Released
Guido van Rossum releases Python with basic list sorting via list.sort(), using a simple comparison-based approach.
2002
Timsort Introduced
Tim Peters creates Timsort, a hybrid sorting algorithm that becomes Python's default. It is optimized for real-world data and remains the engine behind Python sorting today.
2004
sorted() Built-in Added
Python 2.4 introduces the sorted() built-in function, which returns a new sorted list from any iterable without modifying the original.
2008
Python 3.0 — Key Functions Only
Python 3 removes the old cmp parameter and standardizes on key functions as the preferred way to customize sorting behavior.

The central question this lesson addresses is straightforward: how do you sort data in Python when the default alphabetical or numerical order isn't what you need? For example, how would you sort a list of names by their length instead of alphabetically? That's where key functions come in.

Core Principles & Definitions

Before diving into code, let's establish the foundational ideas behind Python's sorting tools. Understanding these principles will make every sorting task feel intuitive.

1

sorted() — Returns a New List

The sorted() function takes any iterable (list, tuple, string, etc.) and returns a brand-new sorted list. The original data remains unchanged.
2

list.sort() — Sorts In Place

The .sort() method modifies the original list directly and returns None. This is called in-place sorting and saves memory for large lists.
3

The key Parameter

Both sorted() and .sort() accept a key parameter — a function that transforms each item before comparison. Python sorts by the transformed values but keeps the original items.
4

The reverse Parameter

Setting reverse=True sorts in descending order (largest to smallest, Z to A). It works alongside key to give you full control over sort direction.
5

Stable Sorting

Python's sort is stable, meaning items that compare as equal keep their original relative order. This is important when sorting by one key after another.
✦ KEY TAKEAWAY
Think of a key function like a label maker. Imagine you have a box of toys and you want to line them up by weight. You don't rearrange the toys differently — you just stick a weight label on each one, sort by the labels, then remove them. The key function creates those temporary labels that Python uses for comparisons.

Visual Explanation — How Key Functions Work

The diagram below shows the step-by-step process that Python follows when you call sorted(words, key=len). Notice how the key function creates temporary "sort keys" that determine the final order, but the output contains the original items — not the key values.

The key function len transforms each string into its length. Python sorts by these key values (3, 4, 6, 10) but returns the original strings in the new order.

The critical insight here is that the key function acts as a transformation layer. Python never actually rearranges the key values themselves — it uses them temporarily to decide the order, then discards them. Your final output always contains the original, untransformed items. This pattern is sometimes called decorate-sort-undecorate because you "decorate" items with sort keys, sort by those keys, then "undecorate" to get the originals back.

How It Works — Syntax & Mechanics

Let's break down the exact syntax for both sorting approaches and see how the key parameter fits in.

SORTED() SYNTAX
sorted(iterable, key=None, reverse=False)
iterable — any collection (list, tuple, string, etc.). key — a function applied to each item before comparison (default: None, meaning compare items directly). reverse — if True, sort in descending order. Returns a new list.
LIST.SORT() SYNTAX
list.sort(key=None, reverse=False)
Same key and reverse parameters, but this is a method on list objects. It modifies the list in place and returns None.

What Can Be a Key Function?

The key parameter accepts any callable that takes one argument and returns a value. This can be a built-in function like len or str.lower, a function you define with def, or a lambda expression (a small anonymous function). For now, we'll focus on built-in functions and simple lambdas.

⚠️ Common Mistake
Don't call the function when passing it as a key! Write key=len (correct — passes the function itself) not key=len() (wrong — calls len with no arguments and causes an error). You are handing Python the function so it can call it on each item.

Here's a quick example using a lambda. A lambda is a tiny one-line function. The expression lambda x: x[1] means "given an item x, return its element at index 1." So sorted(pairs, key=lambda x: x[1]) sorts a list of tuples by their second element.

Common Key Functions — A Classification

Key functions come in many forms. The table below shows the most common patterns you'll encounter, along with what each one does and when to use it.

Common key functions used with sorted() and list.sort()
Key FunctionWhat It DoesExample Use Case
key=lenSorts by the length of each itemSort words shortest to longest
key=str.lowerSorts strings case-insensitivelySort names ignoring capitalization
key=absSorts by absolute valueSort numbers by magnitude
key=lambda x: x[1]Sorts by the second element of each itemSort (name, score) tuples by score
key=lambda s: s[-1]Sorts by the last characterSort words by their ending letter
Side-by-side comparison of sorted() (creates a new list) and list.sort() (modifies the original). Both accept the same key and reverse parameters.

As you can see, choosing between sorted() and list.sort() depends on whether you need to preserve the original list. If you're processing data and want to keep a copy of the unsorted version, sorted() is the safer choice. If you're done with the old order and want to save memory, list.sort() is more efficient.

Worked Example — Sorting Student Records

Let's walk through a realistic scenario. You have a list of student records stored as tuples, and you need to sort them by grade (highest first).

Sort Students by Grade (Descending)
1
Step 1 — Define the DataWe have a list of tuples, where each tuple contains a student's name and their grade: students = [("Alice", 88), ("Bob", 95), ("Charlie", 72), ("Diana", 91)]
2
Step 2 — Identify the KeyWe want to sort by the grade, which is the second element of each tuple (index 1). Our key function is lambda student: student[1]. This takes each tuple and returns just the numeric grade.
3
Step 3 — Choose sorted() or .sort()We'll use sorted() so the original list stays intact. Since we want highest grades first, we also set reverse=True.
4
Step 4 — Write the CodeThe complete expression is: ranked = sorted(students, key=lambda student: student[1], reverse=True)
5
Step 5 — Verify the OutputPython applies the lambda to each tuple: 88, 95, 72, 91. It sorts these values in descending order: 95, 91, 88, 72. Then it returns the original tuples in that order.
[("Bob", 95), ("Diana", 91), ("Alice", 88), ("Charlie", 72)]
💡 Try It Yourself
Open a Python interpreter and paste this code. Then try changing the key to lambda student: student[0] to sort by name instead. Remove reverse=True to see the default ascending order.

sorted() vs list.sort() — Strengths & Limitations

Feature comparison between sorted() and list.sort()
Featuresorted()list.sort()
Return valueNew sorted listNone (modifies in place)
Input typesAny iterable (list, tuple, string, dict, set, generator)Lists only
Original dataPreserved — untouchedOverwritten — old order lost
Memory usageUses extra memory for the new listMore memory-efficient (no copy)
ChainingCan chain with other operations since it returns a listCannot chain — returns None
key & reverse✓ Supported✓ Supported
🔑 WHEN TO USE WHICH
Think of it like editing a photo. sorted() is like applying a filter and saving a copy — the original is still on your camera roll. list.sort() is like editing the original file directly — faster, but the old version is gone. When in doubt, use sorted() because it's safer and more flexible.

Connection to Advanced Sorting Techniques

The key function concept you've learned here is the foundation for more advanced sorting patterns you'll encounter as you progress in Python. Understanding how keys work now will make these techniques easy to pick up later.

From introductory to advanced sorting concepts
What You Know NowWhat's Coming Next
Simple key functions like len and str.lowerMulti-level sorting with operator.itemgetter() and operator.attrgetter()
Lambda functions for simple transformationsCustom classes with __lt__ and other comparison methods
Sorting by one criterionSorting by multiple criteria using tuples as keys, e.g., key=lambda x: (x[1], x[0])
Using reverse=True for descending orderMixing ascending and descending order in multi-key sorts using negative values

One particularly powerful technique is multi-key sorting. Because Python's sort is stable, you can sort by one key, then sort again by another key, and items that tie on the second key will remain in the order established by the first sort. Alternatively, you can return a tuple from your key function to sort by multiple criteria at once. These techniques build directly on everything you've learned in this lesson.

🔭 Looking Ahead
Python's functools.cmp_to_key() function can convert an old-style comparison function into a key function. You won't need this often, but it's good to know it exists for edge cases where a key function alone isn't enough.

Practice Problems

PROBLEM 1 — CONCEPTUAL
What is the difference between sorted(my_list) and my_list.sort()? If you wrote x = my_list.sort(), what value would x hold, and why?
PROBLEM 2 — BASIC CALCULATION
Given words = ["elephant", "cat", "bear", "dolphin"], what is the output of sorted(words, key=len)?
PROBLEM 3 — INTERMEDIATE
You have scores = [("Math", 92), ("English", 85), ("Science", 97), ("History", 85)]. Write an expression using sorted() that sorts these tuples by score in descending order. If two subjects have the same score, should their order change? Explain why or why not.
PROBLEM 4 — APPLIED
You are building a simple contact list app. You have contacts = ["Zara Smith", "alice Johnson", "Bob MARTINEZ", "charlie Lee"]. Users expect contacts sorted alphabetically regardless of capitalization. Write the code to produce a case-insensitive alphabetical sort, and explain which key function you used and why.
PROBLEM 5 — CRITICAL THINKING
Consider the list data = ["3", "15", "7", "100", "22"]. What does sorted(data) return, and why might this surprise you? Then write a version using a key function that sorts these strings by their actual numeric value. Explain the difference.

Lesson Summary

Python provides two primary tools for sorting: sorted(), which returns a new sorted list from any iterable, and list.sort(), which sorts a list in place and returns None. Both methods accept a key parameter — a function that transforms each item into a sort key before comparison — and a reverse parameter to switch between ascending and descending order.

Common key functions include len for sorting by length, str.lower for case-insensitive sorting, int for numeric sorting of strings, and lambda expressions for custom transformations like accessing tuple elements. Python's sort is stable, meaning equal elements retain their original order. The key function creates temporary comparison values but the output always contains the original, untransformed items.

Varsity Tutors • Python • Sorting with Key Functions