FULL PYTHON FIX · 8 MIN READ

How to Sort a List of Dictionaries by Key in Python

sorted(products) cannot compare whole dictionaries. Reproduce the TypeError, select a numeric price key, and test ties without changing the original list.

Before you start: Lists · Dictionaries · Functions

Quick fix

Add key=lambda product: product['price'] to the original sorted() call.

PYTHON
products = [
    {'name': 'Notebook', 'price': 12},
    {'name': 'Pen', 'price': 3},
    {'name': 'Folder', 'price': 8},
]
ordered = sorted(products, key=lambda product: product['price'])
for product in ordered:
    print(product['name'], product['price'])
print('original:', [p['name'] for p in products])
See why this works and test the edge cases

Video guide: How to Sort a List of Dictionaries by Key in Python

The preview is stored on this site. YouTube loads only when you press Play. Watch on YouTube

Read the video transcript

Select a timestamp to watch that moment on YouTube.

  1. 00:00

    Imagine a small shop catalog with a notebook, a pen, and a folder. Each product is a dictionary containing a name and a numeric price. The products are stored in a list, and we want the cheapest item first. A tempting first attempt is to pass the whole list to sorted. Before I run it, what order do you expect? Perhaps the products will appear by name, or perhaps by price. Python cannot know which field matters to our shop unless we tell it. In this pilot, I will stay in the same editor and terminal for the whole investigation. We will run the failing line, use a short inspection to explain the error, supply a sort key, and verify both a tie and the original list.

  2. 00:43

    The terminal results you see are a replay of actual local Python runs, captured for this lesson. The important skill is a repeatable debugging sequence: reproduce the result, inspect the values that are compared, make one change, and run a second case. You can apply the same sequence to a list of students, transactions, or API records. The details of the data change, but the question stays the same: which value should determine the order? Here is our first version in demo dot p y. Three dictionaries have the same two fields, name and price. The final line asks sorted to order the dictionaries themselves.

  3. 01:24

    I run the file without changing the data. The terminal raises a Type Error, saying that less than is not supported between two dictionaries. Notice where the traceback points. It names the line that calls sorted, not one of the dictionary literals. Creating the data worked. Comparing two whole dictionaries did not. A dictionary can hold several different fields, and neither name nor price is automatically its sort order. The exception message gives us a narrower question than the original task. What values did sorted receive, and which one should it compare instead? I will not convert each dictionary to text merely to make the error disappear.

  4. 02:06

    A text representation would sort punctuation and characters, which is not a meaningful rule for product prices. I will also avoid changing the price values until we have evidence that they are wrong. The current prices are integers. The problem is that no key function selected those integers. Keep the traceback visible while we inspect one item. In your own terminal, you can usually work from the last exception line back up to the line of your code that triggered it. I replace the failing call with a small diagnostic. First I print the type of the first element. It is a dictionary, exactly as the error suggested.

  5. 02:46

    Then I loop over the products and display each name, each price, and the type of that price. The terminal shows Notebook twelve, Pen three, and Folder eight; every price type is int. That tells us the values we want to compare are already consistent and numeric. The dictionaries are the containers around those values. A useful sort key takes one product dictionary and returns just its price. Python obtains one key value for each product, compares those keys, and carries the original dictionaries into the new order. This distinction matters because the result should remain a list of full product records, not merely a list of price numbers.

  6. 03:27

    The diagnostic also gives us a predicted answer before we edit the code. Three is smaller than eight, and eight is smaller than twelve. So the names should print as Pen, Folder, Notebook. If the next run differs, we will know our fix or our assumption is wrong. Notice that our diagnostic is small and temporary. It observes the data without changing it. Once the sorting rule is verified, we can remove those print statements from the final program. Now I restore the sorting call and add a key argument. The lambda receives one product at a time and returns product open bracket price close bracket.

  7. 04:07

    We assign the resulting list to ordered, then print each name and price. Run the file again. The terminal prints Pen at three, Folder at eight, and Notebook at twelve. That matches our prediction. The key function did not change the dictionaries; it supplied a comparable number for each one. I print the names from the original products list as a second check. They still appear in their starting order: Notebook, Pen, Folder. That is because sorted creates a new list. If the program needs to rearrange the existing list, list dot sort with the same key is another option, but it changes that list in place. For this example I want to preserve the catalog and create a separate view ordered by price.

  8. 04:52

    There is one more difference worth seeing. A key such as product price expects that field to exist and to contain values that can be compared with one another. If a product has no price, this code will raise a Key Error. That is useful evidence that the input data needs validation; silently inventing a zero price could place an unknown item ahead of a genuinely cheap item. One successful order is not the whole test. I add a Marker at the same price as Folder, eight, and ask for descending order using reverse equals True. Run the new file and inspect the names. Notebook at twelve comes first.

  9. 05:33

    Folder and Marker both cost eight, and they keep their original relative order. Pen at three comes last. Python's sort is stable: equal keys preserve their earlier order, even in this descending result. I print the original product names again, and the input list remains Notebook, Pen, Folder, Marker. That second line catches an accidental in-place sort if we ever refactor this code. Notice that reverse changes the direction of the price comparison; it does not reverse the original list independently after sorting. Try the same program yourself with two new products at equal prices. Predict their relative order, run the file, and then remove reverse to compare the ascending result.

  10. 06:19

    As a second exercise, replace the price key with the name key. That gives an alphabetical order using the same overall pattern. If names might differ in capitalization, think about which string normalization rule you want before assuming ordinary string order is a user-friendly alphabet. Finally, add a product with no price and observe where the error occurs. Decide whether your program should reject that record or ask for a real price before sorting. The related Lists and Dictionaries lessons on PythonLessonLab let you practice the building blocks in an interactive console. For any list of records, remember the workflow: run the failing version, inspect an element, choose the field that defines the order, and verify one edge case.

Run sorted() on the product dictionaries

Imagine a shop catalog stored as a list of dictionaries. Each product has a name and a numeric price, and the task is to show the cheapest product first. Calling sorted(products) seems plausible, but it does not say which field defines the order. Run the same small example used in the video. The list is created successfully; the failure occurs when sorted() tries to compare two dictionary objects.

Read the final exception line and the line of your code named by the traceback. In Python 3, ordinary dictionaries do not support an ordering comparison with <. The error is not evidence that the price numbers are bad, because this version has not selected prices at all. Converting whole dictionaries to strings might suppress the exception while producing an arbitrary order based on punctuation and text. First inspect what the list contains, then choose a field that represents the rule you actually want.

The failing sort from the video
PYTHON
products = [
    {'name': 'Notebook', 'price': 12},
    {'name': 'Pen', 'price': 3},
    {'name': 'Folder', 'price': 8},
]
print(sorted(products))
ERROR (LAST LINE)
TypeError: '<' not supported between instances of 'dict' and 'dict'

Inspect one record and the price values

Print the type of one list item and the name, price, and price type for each product. The items are dictionaries, while every price in this example is an integer. That gives us a testable prediction: if we sort by the prices, Pen should come before Folder, then Notebook. The diagnostic keeps the original records intact and makes the intended comparison explicit before we change the sort call.

The key argument to sorted() receives a function that takes one item and returns its comparison value. For these records, that function can return product['price']. Python computes a key for each product, compares those numeric keys, and places the full dictionaries into a new list. Be deliberate about data quality: a missing price raises KeyError when the key function reads it, and incompatible price types can cause another TypeError. Validate or normalize such inputs according to your program's requirements; do not silently treat an unknown price as zero.

Inspect the actual data
PYTHON
products = [
    {'name': 'Notebook', 'price': 12},
    {'name': 'Pen', 'price': 3},
    {'name': 'Folder', 'price': 8},
]
print('first type:', type(products[0]).__name__)
for product in products:
    print(product['name'], product['price'], type(product['price']).__name__)
OUTPUT
first type: dict
Notebook 12 int
Pen 3 int
Folder 8 int
A missing price is a separate data problem
PYTHON
products = [{'name': 'Pen', 'price': 3}, {'name': 'Mystery'}]
print(sorted(products, key=lambda product: product['price']))
ERROR (LAST LINE)
KeyError: 'price'

Pass a price key to sorted()

Add key=lambda product: product['price'] to the original sorted() call. The lambda is a short function: for each product dictionary, it returns the value stored under 'price'. The terminal now prints Pen at 3, Folder at 8, and Notebook at 12, matching the prediction. The result is still a list of dictionaries, so later code can access each product's name and other fields.

sorted() returns a new list and leaves the order of products unchanged. It does not copy the dictionaries inside that list; both lists still refer to the same product records. If you intentionally want to rearrange the original list instead, use products.sort(key=lambda product: product['price']) and do not assign the method's return value, which is None. Pick one behavior based on whether other code needs the original order. The video's second print statement is a quick check that we chose the new-list behavior.

Sort by price without changing the catalog order
PYTHON
products = [
    {'name': 'Notebook', 'price': 12},
    {'name': 'Pen', 'price': 3},
    {'name': 'Folder', 'price': 8},
]
ordered = sorted(products, key=lambda product: product['price'])
for product in ordered:
    print(product['name'], product['price'])
print('original:', [p['name'] for p in products])
OUTPUT
Pen 3
Folder 8
Notebook 12
original: ['Notebook', 'Pen', 'Folder']
Use list.sort() only when you want to change the list
PYTHON
products = [{'name': 'Notebook', 'price': 12}, {'name': 'Pen', 'price': 3}]
result = products.sort(key=lambda product: product['price'])
print([p['name'] for p in products])
print(result)
OUTPUT
['Pen', 'Notebook']
None

Check equal prices, descending order, and the original list

A successful three-product run does not show what happens when prices tie. Add Marker with the same price as Folder, then sort descending with reverse=True. Notebook comes first at 12. Folder and Marker both cost 8, and Folder stays before Marker because it appeared first in the input. Python's sort is stable: equal keys retain their relative order, including when reverse=True is used. Pen comes last at 3.

Print the original names again to catch an accidental in-place sort. The input remains Notebook, Pen, Folder, Marker. For another boundary test, sorted([], key=...) returns an empty list without calling the key function. Try a different rule, such as sorting by name, only after you decide whether plain string order fits your users. If a price is absent or stored as incompatible text, fix or reject that record before sorting. Verify the rule on a second data set instead of trusting one demonstration.

Verify a stable tie in descending order
PYTHON
products = [
    {'name': 'Notebook', 'price': 12},
    {'name': 'Pen', 'price': 3},
    {'name': 'Folder', 'price': 8},
    {'name': 'Marker', 'price': 8},
]
ordered = sorted(products, key=lambda product: product['price'], reverse=True)
for product in ordered:
    print(product['name'], product['price'])
print('original:', [p['name'] for p in products])
OUTPUT
Notebook 12
Folder 8
Marker 8
Pen 3
original: ['Notebook', 'Pen', 'Folder', 'Marker']
The same rule handles an empty list
PYTHON
products = []
ordered = sorted(products, key=lambda product: product['price'])
print(ordered)
print(products)
OUTPUT
[]
[]
  • A key function selects the comparable field; it does not replace the full records.
  • sorted() returns a new list, while list.sort() changes the existing list and returns None.
  • Equal price keys preserve the input order, even with reverse=True.

Practice the fix

Write sort_products(products, descending=False). Return a new list of product dictionaries ordered by numeric price, using descending=True for highest price first. Keep equal-price products in their input order and leave the original list unchanged. Test a four-product catalog with a price tie and an empty list.

Need a hint?

Return sorted(products, key=lambda product: product['price'], reverse=descending). Do not call products.sort(), because this task must preserve the caller's list order.

Python console

Ready to run

Edit the code and run it in your browser. Examples above can be loaded with Try this example.

Does your code use input()? Add one value per line
Ctrl / ⌘ + Enter to run
OUTPUT
Your output appears here.

Write your solution, then select Check practice.

    Key takeaways

    • A list of dictionaries needs an explicit key when the dictionaries themselves cannot be ordered.
    • Use sorted(products, key=lambda product: product['price']) to order by a numeric field without reordering the input list.
    • Use reverse=True for descending prices; stable ties retain their input order.
    • A missing price or incomparable price type is a separate data problem to validate explicitly.

    What to do next

    1. Review the prerequisite: Lists.
    2. Prove it yourself: Pass the checked task in Lists.
    3. Use it in a project: Sort a finished category report, then run the project source on GitHub .

    Related lessons

    Sources and further reading