runtime
40 / 250
lesson 40 Dictionaries & Sets · beginner

Records inside records

Real records nest: an order has a customer dictionary and a list of line dictionaries. Each pair of brackets goes one level deeper: order["customer"]["city"].

You'll be able to
  • Read a value two levels down, one lookup at a time
  • Loop over a list of dictionaries stored under a key, and total it
  • Update an inner value in place, and tell a KeyError from a TypeError when you take a wrong turn
The idea

An order from an online shop is not flat. It has a customer (a record with a city and a state) and several lines (each with a SKU, a quantity and a price). In Python that is a dictionary whose values include another dictionary and a list of dictionaries, the same shape that web APIs send as JSON.

Read it one step at a time. order["customer"] is the inner dictionary, so order["customer"]["city"] is its city. order["items"] is a list, so you loop over it.

Run each example to see what it prints. Running examples doesn't count toward progress.

example-1.py · One order, two levels deep
order = {
    "order_id": "O104839",
    "customer": {"customer_id": "C00800", "city": "Miami", "state": "FL"},
    "items": [
        {"sku": "ELE-24781", "quantity": 1, "unit_price": 51.49},
        {"sku": "HOM-22847", "quantity": 2, "unit_price": 31.0},
    ],
}
print(order["customer"]["city"])
print(len(order["items"]), "lines")
subtotal = 0
for line in order["items"]:
    subtotal = subtotal + line["quantity"] * line["unit_price"]
print(f"{order['order_id']} to {order['customer']['state']}: {subtotal:.2f}")
example-2.py · A wrong turn at the list
order = {"order_id": "O104839", "items": [{"sku": "ELE-24781", "quantity": 1}]}
print(order["items"]["sku"])

Nested values can be changed in place. Reach the inner dictionary, then store into it. A catalogue keyed by product ID with a small record for each product is a common shape. Selling one unit changes only that product's stock.

example-3.py · A catalogue of product records
catalogue = {
    "P0035": {"name": "Deluxe Pillow", "price": 47.99, "stock": 4},
    "P0146": {"name": "Nordic Handbook", "price": 15.99, "stock": 0},
}
catalogue["P0035"]["stock"] = catalogue["P0035"]["stock"] - 1
catalogue["P0146"]["price"] = 12.99
for product_id, product in catalogue.items():
    status = "in stock" if product["stock"] > 0 else "sold out"
    print(product_id, product["name"], product["price"], status)

When to use it: for records that contain other records, such as API responses, orders with lines, or catalogues of products. Mistakes to avoid:

  • Using a key on a list. Loop over the list first.
  • Guessing the shape. Print the outer value to see whether the next level is a dictionary or a list.
  • Forgetting that a missing key at any level raises KeyError.
Review
  • A value in a dictionary can be another dictionary or a list. Read it one lookup at a time.
  • Loop over a list of dictionaries, and look keys up in each one.
  • A key used on a list raises TypeError, and a missing key at any level raises KeyError.
  • Next module: put these steps into functions you can name, call and test.
Practise this

Loading your progress…

To master this lesson, solve both challenges without hints or the answer, and pass the concept check.

Records inside records — Dictionaries & Sets · Runtime