Python with AI Tutorial · Chapter 16 of 48
Python dictionaries store data as key-value pairs inside curly braces, such as {"name": "Anita", "dept": "Finance"}. You look values up by key instead of by position, which makes a dictionary the natural shape for a record, a lookup table or a set of counts. This chapter covers creating Python dictionaries, reading and updating values, looping, nesting and the most useful dict methods.
Creating and reading a dictionary
Each entry is a key, a colon and a value. Keys must be unique and immutable (strings, numbers and tuples are typical); values can be anything. Read a value with square brackets, or with get() when the key might be missing.
employee = {"name": "Anita Desai", "dept": "Finance", "salary": 61000}
print(employee)
print(employee["name"])
print(employee.get("salary"))
print(employee.get("email", "not provided"))
print(len(employee))
Output:
{'name': 'Anita Desai', 'dept': 'Finance', 'salary': 61000}
Anita Desai
61000
not provided
3
Square brackets raise KeyError for an unknown key; get() returns None or the default you supply. Since Python 3.7 dictionaries remember insertion order, so items always come back in the order they were added.
Adding, changing and removing items
Assigning to a new key adds it; assigning to an existing key replaces the value. update() merges in several pairs at once, pop() removes a key and returns its value and del removes a key without returning anything.
stock = {"laptop": 12, "mouse": 40}
stock["monitor"] = 8
stock["mouse"] = 35
stock.update({"keyboard": 20, "laptop": 10})
print(stock)
removed = stock.pop("mouse")
del stock["monitor"]
print(stock, removed)
Output:
{'laptop': 10, 'mouse': 35, 'monitor': 8, 'keyboard': 20}
{'laptop': 10, 'keyboard': 20} 35
Python dictionary methods
| Method | What it does |
|---|---|
get(key, default=None) |
Value for key, or the default if missing; never raises |
keys() |
View of all keys |
values() |
View of all values |
items() |
View of (key, value) tuples, ideal for loops |
update(other) |
Add or overwrite pairs from another dict or iterable of pairs |
pop(key, default) |
Remove key and return its value |
popitem() |
Remove and return the last inserted pair |
setdefault(key, default) |
Return the value, inserting the default first if the key is missing |
copy() |
Shallow copy |
clear() |
Remove every pair |
dict.fromkeys(keys, value) |
Build a dict with the same value for every key |
Looping through a dictionary
Looping over a dictionary directly gives you the keys. items() gives key and value together, which is what you want almost every time, and values() feeds straight into sum(), max() and friends.
prices = {"Laptop": 899.0, "Monitor": 249.5, "Mouse": 25.0}
for product in prices:
print(product)
for product, price in prices.items():
print(f"{product}: {price:.2f}")
print(list(prices.keys()))
print(sum(prices.values()))
Output: Laptop Monitor Mouse Laptop: 899.00 Monitor: 249.50 Mouse: 25.00 ['Laptop', 'Monitor', 'Mouse'] 1173.5
Nested dictionaries
A dictionary of dictionaries models a table keyed by ID: the outer key finds the row and the inner key finds the column. Chain the square brackets to reach a single cell, and use a comprehension over items() to filter rows.
invoices = {
"INV-101": {"customer": "Acme Ltd", "amount": 1250.0, "paid": True},
"INV-102": {"customer": "Bright Co", "amount": 830.5, "paid": False},
}
print(invoices["INV-102"]["customer"])
unpaid = [inv_id for inv_id, row in invoices.items() if not row["paid"]]
print(unpaid)
invoices["INV-102"]["paid"] = True
print(invoices["INV-102"])
Output:
Bright Co
['INV-102']
{'customer': 'Bright Co', 'amount': 830.5, 'paid': True}
This is also the shape JSON takes when it is loaded into Python, so everything here applies directly to API responses and config files later in the course.
Ask the assistant to convert a small table into a nested dictionary and then to answer questions against it, explaining the lookups.
Turn this table into a nested Python dictionary keyed by employee ID, then write code that answers each question and prints the result: (a) the average salary in Finance, (b) the name of the highest-paid person, (c) a dict of department to head-count. Table: E1 Anita Desai Finance 61000; E2 Rahul Verma Sales 48000; E3 Meera Iyer Finance 72000; E4 Vikram Rao Sales 53000. Use only built-in Python 3.12, no pandas, and explain each dictionary lookup in a comment.
Counting with a dictionary
Counting how often each value appears is the classic dictionary task. get(key, 0) + 1 handles the first sighting and every later one in a single line. For heavier use, collections.Counter is a dictionary subclass built for exactly this.
orders = ["North", "South", "North", "East", "North", "South"]
counts = {}
for region in orders:
counts[region] = counts.get(region, 0) + 1
print(counts)
from collections import Counter
print(Counter(orders).most_common(1))
Output:
{'North': 3, 'South': 2, 'East': 1}
[('North', 3)]
Dictionary comprehensions and zip()
zip() pairs two lists so dict() can turn them into keys and values. A dictionary comprehension builds a new dict from an existing one, transforming values or filtering pairs in one expression.
products = ["Laptop", "Monitor", "Mouse"]
prices = [899.0, 249.5, 25.0]
catalog = dict(zip(products, prices))
print(catalog)
with_tax = {p: round(v * 1.18, 2) for p, v in catalog.items()}
print(with_tax)
expensive = {p: v for p, v in catalog.items() if v > 100}
print(expensive)
Output:
{'Laptop': 899.0, 'Monitor': 249.5, 'Mouse': 25.0}
{'Laptop': 1060.82, 'Monitor': 294.41, 'Mouse': 29.5}
{'Laptop': 899.0, 'Monitor': 249.5}
Sorting a dictionary
Dictionaries cannot be sorted in place, but you can build a new one from sorted items(). To sort by value, pass a key function that picks the second element of each pair. max() with key=d.get finds the key whose value is largest.
salaries = {"Anita": 61000, "Rahul": 48000, "Meera": 72000}
print(sorted(salaries))
by_salary = dict(sorted(salaries.items(), key=lambda kv: kv[1], reverse=True))
print(by_salary)
print(max(salaries, key=salaries.get))
Output:
['Anita', 'Meera', 'Rahul']
{'Meera': 72000, 'Anita': 61000, 'Rahul': 48000}
Meera
Copying and membership
As with lists, = creates a second name for the same dictionary; use copy() for an independent one. The in operator checks keys only, so test values() explicitly when you are looking for a value.
settings = {"theme": "dark", "rows": 50}
backup = settings.copy()
settings["rows"] = 100
print(backup["rows"])
print("theme" in settings)
print("dark" in settings)
print("dark" in settings.values())
Output: 50 True False True
d[key] when the key may not exist and getting a KeyError deep inside a loop. Reach for d.get(key, default) for reads, and d.setdefault(key, []) when you want to create an empty list the first time you see a key and append to it in the same statement: groups.setdefault(dept, []).append(name).Describe a grouping problem from your own data and ask for solutions with setdefault, defaultdict and a plain loop, then compare them.
I have a Python list of (department, employee_name) tuples: [("Finance", "Anita"), ("Sales", "Rahul"), ("Finance", "Meera"), ("Sales", "Vikram"), ("HR", "Priya")]. Show me three ways to build a dictionary that maps each department to a list of its employees: with dict.get, with dict.setdefault and with collections.defaultdict. Print the result of each, confirm they are equal, and explain in plain English which one you would use in a report script and why.
Common mistakes
- Using a list as a key. Keys must be hashable; convert the list to a tuple first.
- Looping with
for k in dand then writingd[k]inside, whenfor k, v in d.items()is clearer and faster. - Adding or removing keys while iterating over the dictionary, which raises
RuntimeError. Iterate overlist(d)instead. - Expecting
"value" in dto search values. It searches keys. - Copying with
=and then modifying one “copy”, which silently changes both.
Exercise
Sales come in as a list of (region, amount) tuples: [("North", 1200), ("South", 980), ("North", 1500), ("East", 430), ("South", 620)]. Build a dictionary of total sales per region, print it, then print each region and its total from highest to lowest, and finally the name of the top region.
Show answer
sales = [("North", 1200), ("South", 980), ("North", 1500), ("East", 430), ("South", 620)]
totals = {}
for region, amount in sales:
totals[region] = totals.get(region, 0) + amount
print(totals)
for region, total in sorted(totals.items(), key=lambda kv: kv[1], reverse=True):
print(f"{region}: {total:,}")
print("Top region:", max(totals, key=totals.get))
Output:
{'North': 2700, 'South': 1600, 'East': 430}
North: 2,700
South: 1,600
East: 430
Top region: North
The get(region, 0) pattern means no region needs to be initialised in advance, and the sorted items() loop leaves the original dictionary untouched.
Related chapters
- Python Lists – the ordered collection dictionaries are often built from.
- Python Sets – unique keys without values.
- Python JSON – dictionaries in and out of JSON files and APIs.
- Python with AI course hub – all 48 chapters in order.
FAQ
Are Python dictionaries ordered?
Yes, since Python 3.7. A dictionary keeps the order in which keys were inserted, so loops, keys() and items() always return pairs in that order. You still look values up by key, not by position.
How do I check if a key exists in a dictionary?
Use the in operator: if “email” in employee. It checks keys only and is very fast. To read a value that may be missing without an error, use employee.get(“email”, default).
What is the difference between d[key] and d.get(key)?
d[key] raises KeyError when the key is missing. d.get(key) returns None instead, or a default value you pass as the second argument, which makes it the safer choice when the key is optional.
Working with spreadsheets too? Ready-made Excel, Google Sheets and Power BI templates are at NextGenTemplates.com.
Chapter 16 of 48 · Python with AI: all 48 chapters



