What is it? #
A dictionary stores values under names rather than positions. Instead of remembering that the email is at index 2, you ask for user["email"].
Each entry is a key and a value. Keys must be unique and hashable — strings, numbers and tuples work; lists do not. Values can be anything, including other dictionaries.
Lookups are fast no matter how many keys there are. Python hashes the key and jumps to the right slot, so a dictionary with a million entries answers about as quickly as one with ten.
Since Python 3.7, dictionaries remember the order keys were inserted. That is convenient for display, but you should still think of a dictionary as "lookup by name", not "list with labels".
Think of it like this #
A dictionary is a contacts app. You do not scroll to position 47 to find a phone number — you type the name. The name is the key, the number is the value, and each name appears once.
Simple example #
You are handling a user record. It has a name, an email, a role and a nested set of preferences. Some fields may be missing, so you need a way to read them without crashing.
Code #
user = {
"name": "Ravi",
"email": "[email protected]",
"role": "editor",
"prefs": {"theme": "dark", "emails": False},
}
print(user["name"]) # Ravi
print(user.get("phone")) # None — no crash
print(user.get("phone", "not provided")) # not provided
user["role"] = "admin" # update
user["last_login"] = "2026-09-22" # add
del user["email"] # remove
print("role" in user) # True
print(list(user.keys()))
print(user["prefs"]["theme"]) # dark
for key, value in user.items():
print(f"{key}: {value}")
# Counting with a dictionary
words = ["api", "db", "api", "cache", "api"]
counts = {}
for word in words:
counts[word] = counts.get(word, 0) + 1
print(counts) # {'api': 3, 'db': 1, 'cache': 1}
How it works #
user["name"] looks up a key directly. If the key is missing you get a KeyError and the program stops, which is the right behaviour when the key is genuinely required.
user.get("phone") returns None instead of raising. The second argument sets a different fallback. Use [] when a missing key is a bug, and .get() when it is expected.
Assigning to a key that does not exist creates it; assigning to one that does replaces the value. There is no separate "add" and "update" operation.
del user["email"] removes a key. user.pop("email", None) does the same without raising when the key is absent.
"role" in user checks the keys, not the values — a detail worth remembering.
.items() gives you key and value together, which is why the loop can unpack into two names. .keys() and .values() exist for when you only need one side.
The counting block is the pattern you will reuse most. counts.get(word, 0) + 1 reads "whatever is there, or zero, plus one". It replaces an if-else and is the reason collections.Counter exists in the standard library for the same job.
Real-world use #
Dictionaries are the shape of almost all data that crosses a boundary. JSON from an API becomes a dictionary. A database row becomes a dictionary. Configuration files, form submissions, HTTP headers and environment variables all arrive as key-value pairs.
That makes .get() one of the most important habits in real Python. Data from outside your program is untrustworthy, and half of it will be missing a field you assumed was always there.
Counting and grouping with dictionaries is everywhere too: requests per endpoint, errors per type, sales per region. When your dictionary gets deeply nested, that is usually the signal to introduce a class or a dataclass instead, which you will meet on Day 22.
Common mistakes #
- Using
user["field"]on data from an API. External data is missing fields all the time — use.get()with a default. - Assuming
"value" in my_dictchecks values. It checks keys; usein my_dict.values()for values. - Trying to use a list as a key. Keys must be hashable, so convert to a tuple.
- Changing a dictionary while looping over it. Iterate over
list(d.keys())if you need to add or delete during the loop. - Nesting five levels deep and then debugging it with print. At that depth, a class or dataclass is easier to work with.
Practice #
Build a dictionary describing a product (name, price, in stock). Print the price using a safe lookup with a default. Add a "category" key, remove one key, then loop over the dictionary printing key: value lines. Finally, count how often each word appears in "red blue red green blue red".