Free demoJob-oriented courses at Debugshala, Old Palasia, Indore. Freshers, non-IT and year-gap welcome.Book a free demo +91-8982385539

Sorting in Python: sorted() vs sort(), key Functions and Ranks

Lesson 23 of 52 · 9 min · Updated 13 Nov 2026

Learn sorting in Python with sales data: sorted() vs list.sort(), reverse, key functions, sorting dicts by value, multi-column sorts and stable sorting.

Imagine the owner of a mobile accessories shop in Chhoti Gwaltoli asks you for "the salespeople, best first". Simple enough. Then she adds, "and if two people sold the same amount, put the one with fewer returns first". Then, "actually, group them by branch, and inside each branch, best first".

Each request is the same list of salespeople, put in a different order. What changes is the rule you use to compare two people: their sales, then their returns, then their branch and sales together.

In Python, that comparison rule is the key. You do not write the sorting algorithm yourself. You tell Python what value to look at for each item, and it does the rest.

Sorting in Python means arranging the items of an iterable in order using the built-in sorted() function or the list.sort() method, optionally guided by a key function that computes the value each item is compared by.

This lesson builds on list and dict comprehension and on the lists article. All examples target Python 3.12+, but sorting has worked this way for many years.

sorted() vs list.sort(): what is the difference?

Both use the same algorithm and accept the same key and reverse arguments. The difference is what they change and what they return.

sorted(iterable) my_list.sort()
Works on Any iterable: list, tuple, set, dict, string Lists only
Original data Left unchanged Reordered in place
Returns A new sorted list None
Use when You need to keep the original order too You no longer need the old order
Python
sales = [48000, 125000, 76500, 125000, 39900]

ranked = sorted(sales, reverse=True)
print("New list:", ranked)
print("Original:", sales)

sales.sort()
print("Sorted in place:", sales)

result = sales.sort()
print("sort() returns:", result)          # None, a classic trap

print(sorted("indore"))                   # a string becomes a sorted list of characters
print(sorted({"Ujjain", "Bhopal", "Indore"}))

The line result = sales.sort() is worth staring at. Writing sales = sales.sort() throws away your list and leaves you holding None. If you want the sorted list as a value, use sorted().

Quick check

What is the value of x after x = [3, 1, 2]; x = x.sort()?

How does the key argument work?

The key argument takes a function. Python calls it once for each item, gets back a sort key, and orders the items by those keys. The original items are what end up in the result; the keys are only used for comparing.

How the Python sort key function computes a value for each item and orders the items by those values

The key function turns each item into the value Python compares; the result still contains the original items.

Python
names = ["ravi", "Neha", "asha", "Zoya", "mohit"]

print(sorted(names))                   # uppercase sorts before lowercase
print(sorted(names, key=str.lower))    # case-insensitive
print(sorted(names, key=len))          # shortest first

def last_digit(code):
    return int(code[-1])

codes = ["INV-27", "INV-31", "INV-19", "INV-42"]
print(sorted(codes, key=last_digit))

Notice that you pass the function itself, key=str.lower, without brackets. Writing key=str.lower() would call it immediately and fail.

Plain sorted(names) puts "Neha" and "Zoya" before "asha" because uppercase letters have smaller character codes than lowercase ones. key=str.lower compares lowercase copies while keeping the original spellings in the output.

Small one-off key functions are often written inline as lambda expressions, such as key=lambda row: row[1]. The lambda tutorial covers that syntax properly; in this article we use it only in its simplest form.

Quick check

Which call sorts the words by length, shortest first?

Sorting lists of tuples and records

Real data usually comes as rows. Tuples compare item by item: first elements first, and only if those are equal, the second elements. So sorting rows without a key sorts by the first column, with later columns breaking ties.

Python
from operator import itemgetter

team = [
    ("Ravi", "Rajwada", 125000, 3),
    ("Neha", "Palasia", 98000, 1),
    ("Asha", "Rajwada", 125000, 1),
    ("Mohit", "Palasia", 143000, 4),
]

print([r[0] for r in sorted(team)])                          # by name
by_sales = sorted(team, key=itemgetter(2), reverse=True)
for name, branch, amount, returns in by_sales:
    print(f"{name:<6} {branch:<8} {amount:>7,}  returns={returns}")

operator.itemgetter(2) builds a small function that returns item 2 of whatever it is given. It does the same job as lambda r: r[2], reads clearly and is slightly faster. For dictionaries, itemgetter("sales") works the same way.

How do you sort by multiple keys in Python?

Back to the shop owner's second request: sales high to low, and for equal sales, fewer returns first. One direction is descending and the other ascending. There are two clean ways to handle that.

Option 1: a tuple key with a negated number

Return a tuple from the key. Python compares the first part, then the second. To flip one numeric column, negate it.

Python
team = [
    ("Ravi", "Rajwada", 125000, 3),
    ("Neha", "Palasia", 98000, 1),
    ("Asha", "Rajwada", 125000, 1),
    ("Mohit", "Palasia", 143000, 4),
]

def rank_key(row):
    name, branch, amount, returns = row
    return (-amount, returns)          # amount descending, returns ascending

for row in sorted(team, key=rank_key):
    print(row[0], row[2], row[3])

Asha and Ravi both sold Rs 1,25,000, so the second part of the key, returns, decides: Asha's 1 beats Ravi's 3.

Option 2: two stable passes

Negation only works for numbers. For text columns in mixed directions, rely on stability: Python's sort never reorders items whose keys are equal. Sort by the least important column first, then by the most important.

Stable sorting in Python shown as two passes, first by sales then by branch, keeping sales order inside each branch

The second pass groups by branch; because the sort is stable, each branch keeps the sales order from the first pass.

Python
team = [
    ("Ravi", "Rajwada", 125000), ("Neha", "Palasia", 98000),
    ("Asha", "Rajwada", 131000), ("Mohit", "Palasia", 143000),
    ("Zoya", "Vijay Nagar", 87000),
]

step1 = sorted(team, key=lambda r: r[2], reverse=True)   # secondary: sales, high first
step2 = sorted(step1, key=lambda r: r[1])                # primary: branch A to Z
for name, branch, amount in step2:
    print(f"{branch:<12} {name:<6} {amount:>7,}")

This two-pass trick is exactly what the official Sorting HOWTO recommends for complex orderings. It also matches how you would sort a spreadsheet by hand: last criterion first.

How do you sort a dictionary by value?

A dictionary has no sort() method, but sorted() accepts its items(), which are (key, value) pairs. Sort the pairs by their second element, and rebuild a dictionary if you need one. Since dictionaries keep insertion order, the new dictionary stays sorted.

Python
branch_sales = {"Rajwada": 256000, "Palasia": 241000, "Vijay Nagar": 87000, "Sarafa": 312000}

ranked = sorted(branch_sales.items(), key=lambda kv: kv[1], reverse=True)
print(ranked)

top = dict(ranked[:2])
print("Top 2:", top)

print(sorted(branch_sales))                                  # keys only, A to Z
print(sorted(branch_sales, key=branch_sales.get))           # keys, by value
for rank, (branch, amount) in enumerate(ranked, start=1):
    print(f"#{rank} {branch:<12} Rs {amount:,}")

The dictionaries tutorial explains items() and get if either is unfamiliar. For "the top 3 out of a million", heapq.nlargest(3, data, key=...) avoids sorting everything.

Sorting text that contains numbers

Strings sort character by character, so "INV-10" comes before "INV-9": the character "1" is smaller than "9". Spreadsheet users meet this all the time. The fix is a key that pulls out the number.

Python
invoices = ["INV-9", "INV-10", "INV-2", "INV-101", "INV-33"]
print(sorted(invoices))                                   # text order

print(sorted(invoices, key=lambda s: int(s.split("-")[1])))   # numeric order

amounts = ["1,250", "980", "12,400", "3,005"]
print(sorted(amounts, key=lambda s: int(s.replace(",", ""))))

Common mistakes when sorting in Python

  • Assigning the result of sort(). data = data.sort() sets data to None. Use data.sort() alone, or data = sorted(data).
  • Calling the key function. key=len() is wrong; pass key=len.
  • Mixing types. sorted([3, "10", 7]) raises TypeError because Python 3 will not compare numbers with strings. Convert first.
  • None in the data. None cannot be compared with numbers either. Use a key such as lambda x: (x is None, x or 0) to push missing values to the end.
  • Case surprises. Capitalised words sort first unless you use key=str.lower.
  • Number-like text. "INV-10" sorts before "INV-9" until you extract the number in the key.

Key takeaways

  • sorted() returns a new list from any iterable; list.sort() reorders a list and returns None.
  • reverse=True gives descending order.
  • key= takes a function that computes the comparison value for each item.
  • A tuple key sorts by several columns; negate a number to flip its direction.
  • Sorting is stable, so two passes, least important first, handle any mix of directions.
  • Sort a dict by value with sorted(d.items(), key=lambda kv: kv[1]).

The next lesson tours the collections module, whose Counter.most_common() sorts counts for you.

Take the free Python Programming quiz10 quick questions with explanations. No sign-up needed, and you can come back to this lesson after.

FAQ

What is the difference between sort() and sorted() in Python?

sorted() is a built-in function that accepts any iterable and returns a new sorted list, leaving the original untouched. sort() is a list method that reorders the list in place and returns None. Both accept key and reverse. Use sorted() when you must keep the original order.

How do I sort a list in descending order in Python?

Pass reverse=True, as in sorted(sales, reverse=True) or sales.sort(reverse=True). This reverses the comparison while keeping the sort stable. For a single numeric column inside a tuple key, you can also negate the value, such as key=lambda r: -r[2].

Is Python's sort stable?

Yes. Python guarantees that sorted() and list.sort() are stable, meaning items with equal keys keep their original relative order. This makes multi-pass sorting reliable: sort by the secondary column first, then by the primary column, and the secondary order survives inside each group.

Which sorting algorithm does Python use?

CPython uses Timsort, a hybrid of merge sort and insertion sort that is fast on real data containing partly ordered runs. Since Python 3.11 it decides the order of merges with a refined policy known as Powersort. The worst case is O(n log n), and the sort is stable.

Where can I learn sorting and data handling in Python in Indore?

Debugshala teaches Python for analytics in classrooms at Old Palasia, Indore, in English and Hindi, and welcomes non-IT graduates and people with a year gap. Start with a free demo of Debugshala's analyst course in Old Palasia, and practise sorting questions on Debugshala Test.

From the team behind this site

Go further with the Data Analytics Course at Debugshala

These tutorials are written by Debugshala, a training and placement institute at Old Palasia, Indore. The classroom course adds live mentoring, real projects and interview preparation.

  • Offline classes at Old Palasia, Indore
  • Free demo class before you pay
  • Non-IT, fresher and year-gap friendly
  • Placement assistance

700+ students placed · 200+ hiring partners · 4.9★ Google rating

Python List Comprehension: Syntax, if-else, Dict and Set FormsPython collections Module: Counter, defaultdict and deque