Dictionaries
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.
student = {
"name": "Ananya",
"age": 20,
"city": "Kochi",
"subjects": ["Maths", "Physics"],
}
print(student["name"])
print(student["subjects"][0])
print(len(student), "keys")
print(student)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.
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)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.
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){'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 raiseKeyErrorif the key is missing, unless you givepop()a default:prices.pop("lassi", None).a | bmakes a new merged dictionary; when both have the same key, the value frombwins.a |= bupdatesain 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.
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}")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.
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){'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.
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}")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"]raisesKeyError. Used.get("phone")when the key may be missing. - Expecting
into search values.inchecks keys. Usevalue in d.values()for values. - Changing a dictionary while looping over it. This raises
RuntimeError. Loop overlist(d)or build a new dictionary. - Thinking
b = acopies a dictionary. As with lists, both names share one dictionary. Usea.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]raisesKeyErrorfor a missing key;d.get(key, default)does not.- Assign to add or change;
update(),pop(),deland|add, remove and merge entries. - Loop with
for key, value in d.items():;inchecks keys only. get(key, 0) + 1counts andsetdefault(key, []).append(x)groups.- Python 3.15's built-in
frozendictis immutable, hashable and not adictsubclass.
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
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}")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?
get() returns the default value you pass when the key is missing.
2. With d = {"tea": 20}, what is 20 in d?
in checks the keys of a dictionary, and 20 is a value, not a key.
3. What does {"a": 1, "b": 2} | {"b": 3} produce?
When both dictionaries share a key, the value from the right-hand side wins.
4. Which statement about Python 3.15's frozendict is true?
A frozendict is immutable and hashable, and it is a separate type from dict.
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
