Dictionaries

Python · Lesson 21 of 56 6 min read Updated

A list finds values by position: item 0, item 1, item 2. But most real data is looked up by a name: the price of "tea", the marks of "Priya", the phone number of "Kabir". A dictionary (type dict) stores values under keys, so you can find any value straight from its key.

In this lesson you will create dictionaries, read values safely, add, change and remove entries, loop over keys and values, count and group things, merge dictionaries, and meet the immutable frozendict added in Python 3.15.

Creating a dictionary

Write key: value pairs inside curly braces, separated by commas. Each key appears only once and points to one value.

PythonRun it yourself
student = {
    "name": "Ananya",
    "age": 20,
    "city": "Kochi",
    "subjects": ["Maths", "Physics"],
}

print(student["name"])
print(student["subjects"][0])
print(len(student), "keys")
print(student)
Output
Ananya
Maths
4 keys
{'name': 'Ananya', 'age': 20, 'city': 'Kochi', 'subjects': ['Maths', 'Physics']}
  • Keys are usually strings, but any hashable value works: numbers, strings, tuples. A list cannot be a key, because it can change.
  • Values can be anything: numbers, strings, lists, even other dictionaries.
  • Dictionaries remember insertion order: items come out in the order you added them.

Reading values safely

student["name"] gets a value by its key. If the key does not exist, Python raises a KeyError. When a key might be missing, use get(), which returns None or a default value you choose instead.

PythonRun it yourself
student = {"name": "Ananya", "age": 20, "city": "Kochi"}

print(student.get("city"))
print(student.get("phone"))
print(student.get("phone", "not given"))

print("age" in student)
print(20 in student)
Output
Kochi
None
not given
True
False

The in operator checks keys, not values. That is why 20 in student is False even though 20 is one of the values. To search the values, use 20 in student.values().

Adding, changing and removing

Assigning to a key adds it if it is new, or replaces its value if it already exists.

PythonRun it yourself
prices = {"tea": 20, "coffee": 30}

prices["lassi"] = 50          # add a new key
prices["tea"] = 25            # change an existing value
prices.update({"vada": 15, "coffee": 35})
print(prices)

removed = prices.pop("lassi")
del prices["vada"]
print("Removed lassi at", removed)
print(prices)

festival = prices | {"jalebi": 40}
print(festival)
Output
{'tea': 25, 'coffee': 35, 'lassi': 50, 'vada': 15}
Removed lassi at 50
{'tea': 25, 'coffee': 35}
{'tea': 25, 'coffee': 35, 'jalebi': 40}
  • update() adds or replaces several entries at once.
  • pop(key) removes a key and returns its value; del d[key] just removes it. Both raise KeyError if the key is missing, unless you give pop() a default: prices.pop("lassi", None).
  • a | b makes a new merged dictionary; when both have the same key, the value from b wins. a |= b updates a in place.

Looping over a dictionary

A for loop over a dictionary gives you its keys. Use values() for just the values and items() for (key, value) pairs, which you unpack in the loop header.

PythonRun it yourself
bill = {"Masala dosa": 120, "Filter coffee": 40, "Idli": 60}

for item in bill:
    print(item)

total = sum(bill.values())
print("Total: ₹", total)

for item, price in bill.items():
    print(f"{item:<14} ₹{price:>4}")
Output
Masala dosa
Filter coffee
Idli
Total: ₹ 220
Masala dosa    ₹ 120
Filter coffee  ₹  40
Idli           ₹  60

items() is the one you will use most. Do not add or remove keys while looping over the same dictionary: Python stops with RuntimeError: dictionary changed size during iteration. Loop over list(bill) instead, or build a new dictionary with a comprehension, as you saw in Comprehensions.

Counting and grouping

Two patterns come up again and again. To count things, use get(key, 0) + 1, so the first time a key is seen it starts from 0. To group things, use setdefault(key, []), which returns the existing list or creates an empty one.

PythonRun it yourself
orders = "tea coffee tea lassi tea coffee"

counts = {}
for drink in orders.split():
    counts[drink] = counts.get(drink, 0) + 1
print(counts)

students = [("Aarav", "Pune"), ("Isha", "Kochi"), ("Rohan", "Pune")]
by_city = {}
for name, city in students:
    by_city.setdefault(city, []).append(name)
print(by_city)
Output
{'tea': 3, 'coffee': 2, 'lassi': 1}
{'Pune': ['Aarav', 'Rohan'], 'Kochi': ['Isha']}

Counting is so common that the standard library has collections.Counter for it: Counter(orders.split()).most_common(2) gives the two most popular drinks. You will see it in Standard Library Tour.

Nested dictionaries

A value can itself be a dictionary, which is how real-world records are stored. A dictionary of dictionaries looks just like the JSON data that web APIs send, which you will meet in JSON & CSV.

PythonRun it yourself
results = {
    "Aarav": {"maths": 72, "science": 88},
    "Meera": {"maths": 95, "science": 81},
}

print(results["Meera"]["maths"])

for name, marks in results.items():
    average = sum(marks.values()) / len(marks)
    print(f"{name}: {average:.1f}")
Output
95
Aarav: 80.0
Meera: 88.0

results["Meera"] gives Meera's inner dictionary, and ["maths"] then reads from it.

Common mistakes

  • Reading a missing key with []. d["phone"] raises KeyError. Use d.get("phone") when the key may be missing.
  • Expecting in to search values. in checks keys. Use value in d.values() for values.
  • Changing a dictionary while looping over it. This raises RuntimeError. Loop over list(d) or build a new dictionary.
  • Thinking b = a copies a dictionary. As with lists, both names share one dictionary. Use a.copy().
  • Using a list as a key. Lists are unhashable. Use a tuple, such as ("Pune", "Mumbai").

Key points

  • A dictionary maps unique, hashable keys to values: {"tea": 20, "coffee": 30}.
  • d[key] raises KeyError for a missing key; d.get(key, default) does not.
  • Assign to add or change; update(), pop(), del and | add, remove and merge entries.
  • Loop with for key, value in d.items():; in checks keys only.
  • get(key, 0) + 1 counts and setdefault(key, []).append(x) groups.
  • Python 3.15's built-in frozendict is immutable, hashable and not a dict subclass.

Exercise

A school canteen in Jaipur has the menu menu = {"samosa": 15, "chai": 10, "poha": 30}. Raise the price of poha to 35 and add "kachori" at ₹20. Then process this order: order = ["chai", "samosa", "chai", "kachori", "pizza"]. Count how many of each item was ordered, skipping (and printing a message for) items that are not on the menu. Finally print each item's quantity and cost, and the grand total.

Show solution
Python
menu = {"samosa": 15, "chai": 10, "poha": 30}
menu["poha"] = 35
menu["kachori"] = 20

order = ["chai", "samosa", "chai", "kachori", "pizza"]
counts = {}
for item in order:
    if item not in menu:
        print(f"Sorry, no {item} today")
        continue
    counts[item] = counts.get(item, 0) + 1

total = 0
for item, qty in counts.items():
    cost = qty * menu[item]
    total += cost
    print(f"{item:<8} x{qty}  ₹{cost}")
print(f"Total: ₹{total}")
Output
Sorry, no pizza today
chai     x2  ₹20
samosa   x1  ₹15
kachori  x1  ₹20
Total: ₹55

in checks whether each item is a key of menu before counting it. The second loop unpacks items() and looks up each price with menu[item], which is safe because only menu items were counted.

Quick Quiz

1. What does {"a": 1, "b": 2}.get("c", 0) return?

2. With d = {"tea": 20}, what is 20 in d?

3. What does {"a": 1, "b": 2} | {"b": 3} produce?

4. Which statement about Python 3.15's frozendict is true?

Learn Python with a mentor

Free lessons get you started. Our Python Programming training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call