Dictionaries in Python
Say you're storing students' grades. The first idea is two lists, names and grades, with matching positions linking them.
Python 3.13names = ["John", "Mary", "Kate"] grades = [90, 75, 80]
To find Mary's grade you first have to locate her position in names, then read the same position in grades. Add a student and you must remember to append to the second list too. Let one list drift by a single element and Mary gets someone else's grade, and the program won't say a word. The link between a name and a grade lives only in your head, not in the code.
A dictionary removes the index middleman and ties the name straight to its value.
Python 3.13grades = {"John": 90, "Mary": 75, "Kate": 80} print(grades["Mary"])75
A phone book works the same way: you find a person by name, not by line number.
Creating a dictionary
Most often a dictionary is written directly, in curly braces: a key: value pair, pairs separated by commas.
Python 3.13# An empty dictionary to fill later prices = {} # A dictionary with data right away person = {"name": "John", "age": 30, "city": "New York"} print(person){'name': 'John', 'age': 30, 'city': 'New York'}
If the pairs already exist somewhere, for instance arriving as pairs, you can build a dictionary with the dict() function.
Python 3.13pairs = [("name", "Anna"), ("age", 28), ("city", "Berlin")] person = dict(pairs) print(person){'name': 'Anna', 'age': 28, 'city': 'Berlin'}
Reading a value: brackets vs get
The most direct way to get a value is square brackets with the key.
Python 3.13person = {"name": "John", "age": 30} print(person["name"])John
But if the key isn't in the dictionary, the brackets don't return emptiness, they stop the program with a KeyError.
Python 3.13person = {"name": "John", "age": 30} print(person["phone"]) # KeyError: 'phone' — there's no such key
This isn't a flaw but a safeguard: most often reaching for a missing key is a typo or broken logic, and it's better to hear about it immediately. Brackets fit when you're sure the key exists.
When a key might be absent, there's the get() method. It returns None instead of an error, and if you pass a second argument, that argument becomes the default value.
Python 3.13person = {"name": "John", "age": 30} print(person.get("phone"))Noneprint(person.get("phone", "not provided"))not provided
Hence a simple rule of thumb: brackets when a missing key is an error, get() when a missing key is a normal case you're ready to handle.
Adding and changing
A dictionary uses the same syntax to add a key and to change an existing one: assignment by key. If the key wasn't there, it appears; if it was, the value is overwritten.
Python 3.13person = {"name": "John", "age": 30} # Key "city" didn't exist — it gets added person["city"] = "New York" print(person){'name': 'John', 'age': 30, 'city': 'New York'}# Key "age" already exists — the value is replaced person["age"] = 31 print(person){'name': 'John', 'age': 31, 'city': 'New York'}
When you need several changes at once, update() is handier: it adds new keys and overwrites matching ones in a single call.
Python 3.13person = {"name": "John", "age": 31} person.update({"age": 32, "job": "developer"}) print(person){'name': 'John', 'age': 32, 'job': 'developer'}
Checking whether a key exists
To find out in advance whether a key is present, use the in operator. This is exactly how you avoid a KeyError when you do need the brackets.
Python 3.13person = {"name": "John", "age": 30} print("name" in person)Trueprint("phone" in person)False
Removing
You can drop a key with the del operator. But if the key isn't there, del also fails with a KeyError.
Python 3.13person = {"name": "John", "age": 30, "job": "developer"} del person["job"] print(person){'name': 'John', 'age': 30}
The pop() method removes a key and returns its value at the same time, which helps when you still need the value being removed. With a second argument it doesn't fail on a missing key but returns the default instead.
Python 3.13person = {"name": "John", "age": 30} age = person.pop("age") print(age)30# Key "phone" doesn't exist, but the second argument saves us from an error phone = person.pop("phone", "not provided") print(phone)not provided
Iterating over a dictionary
You can walk through a dictionary with a loop. By default a for loop goes over the keys, and the value is easy to fetch by key.
Python 3.13grades = {"John": 90, "Mary": 75, "Kate": 80} for name in grades: print(name, ":", grades[name])John : 90 Mary : 75 Kate : 80
If you need both the key and the value inside the loop, the items() method hands them over as a pair at once, with no lookup by key.
Python 3.13grades = {"John": 90, "Mary": 75, "Kate": 80} for name, grade in grades.items(): print(name, ":", grade)John : 90 Mary : 75 Kate : 80
There are matching methods too: keys() gives only the keys, values() only the values. They're useful when the other half of the pair isn't needed in the loop.
Python 3.13grades = {"John": 90, "Mary": 75, "Kate": 80} total = 0 for grade in grades.values(): total = total + grade print("Total points:", total)Total points: 245
A common task: counting
A dictionary is a great fit for counting something: the key is the object, the value is the counter. Let's count how many times each word appears.
The straightforward version looks like this: for each word we check whether we've seen it before, and either bump the counter or start a new one.
Python 3.13text = "one two one two three" words = text.split() counts = {} for word in words: if word in counts: counts[word] = counts[word] + 1 else: counts[word] = 1 print(counts){'one': 2, 'two': 2, 'three': 1}
This is exactly where get() with a default helps: "take the current counter, and if the word wasn't there yet, treat it as zero." The if/else collapses into one line.
Python 3.13text = "one two one two three" words = text.split() counts = {} for word in words: counts[word] = counts.get(word, 0) + 1 print(counts){'one': 2, 'two': 2, 'three': 1}
What can be a key
Keys live by two rules, and both follow from how a dictionary is built internally.
- Keys are unique. You can't write two identical keys: the second assignment simply overwrites the first. That makes sense — otherwise it would be unclear which value the key "Mary" should return.
- A key must be immutable. Strings, numbers, and tuples work. A list can't be a key: Python finds a value by the key through its immutable contents, and a list could be changed after it became a key, which would "lose" the value.
Python 3.13# A list as a key — an error broken = {[1, 2]: "value"} # TypeError: unhashable type: 'list'
Values, on the other hand, can be anything: numbers, strings, lists, even other dictionaries.
Check your understanding
What does print(person["phone"]) output if the dictionary person has no "phone" key?
