Dictionaries in Python
Reviewed & published by Brayan K
Store and access data using key-value pairs for fast and organized data management.
Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
- What a dictionary is and how key-value pairs work
- The difference between lists and dictionaries — when to use which
- How to safely access values using .get() vs square brackets
- How to add, update, and delete key-value pairs
- How to loop through keys, values, and items
- Nested dictionaries and real-world use cases
1. What Are Dictionaries?
A dictionary stores data in key-value pairs. Instead of accessing items by position (like lists), you access them by a unique key name.
Key Characteristics
- Key-value pairs — Each item has a name (key) and data (value)
- Fast lookups — Access any value instantly by its key
- Unique keys — Each key can only appear once
- Mutable — You can add, change, or remove items
- Ordered — Maintains insertion order (Python 3.7+)
2. Lists vs Dictionaries
Understanding when to use each:
| Feature | List | Dictionary |
|---|---|---|
| Access by | Index (0, 1, 2...) | Key name |
| Syntax | [item1, item2] | |
| Best for | Ordered collections | Named/labeled data |
| Example use | List of names | User profile info |
fruits = ["apple", "banana"]
print(fruits[0]) # appleperson = {"name": "Alice"}
print(person["name"]) # Alice3. Creating Dictionaries
| Method | Example | Description |
|---|---|---|
| Empty dictionary | my_dict = {} | Start with nothing |
| With data | Key-value pairs | |
| Using dict() | dict(name="Alice") | Constructor function |
# Different ways to create dictionaries
# Empty dictionary
my_dict = {}
print("Empty:", my_dict)
# Dictionary with data
person = {
"name": "Alice",
"age": 25,
"city": "London"
}
print("Person:", person)
# Using dict() constructor
info = dict(name="Bob", age=30, job="Developer")
print("Info:", info)
# Mixed value types
product = {
"id": 101,
"name": "Laptop",
"price": 999.99,
"in_stock": True
}
print("Product:", product)
# ✅ Expected output:
# Empty: {}
# Person: {'name': 'Alice', 'age': 25, 'city': 'London'}
# Info: {'name': 'Bob', 'age': 30, 'job': 'Developer'}
# Product: {'id': 101, 'name': 'Laptop', 'price': 999.99, 'in_stock': True}4. Accessing Values
There are two ways to access dictionary values:
| Method | Syntax | If Key Missing |
|---|---|---|
| Square brackets | dict["key"] | KeyError (crashes) |
| .get() method | dict.get("key") | Returns None (safe) |
| .get() with default | dict.get("key", "default") | Returns your default |
person = {"name": "Alice", "age": 25}
# Method 1: Square brackets (fast but risky)
print("Name:", person["name"])
# Method 2: .get() method (safe)
print("Age:", person.get("age"))
# .get() with missing key
print("Email:", person.get("email")) # Returns None
print("Email:", person.get("email", "N/A")) # Returns "N/A"
# Square brackets with missing key would crash:
# print(person["email"]) # KeyError!
# ✅ Expected output:
# Name: Alice
# Age: 25
# Email: None
# Email: N/A5. Adding and Changing Items
Dictionaries are mutable — you can add new key-value pairs or update existing ones using the same syntax:
person = {"name": "Alice"}
print("Start:", person)
# Add new key-value pair
person["age"] = 25
print("After adding age:", person)
# Add another
person["city"] = "London"
print("After adding city:", person)
# Change existing value
person["age"] = 26
print("After changing age:", person)
# Add multiple with .update()
person.update({"job": "Developer", "country": "UK"})
print("After update:", person)
# ✅ Expected output:
# Start: {'name': 'Alice'}
# After adding age: {'name': 'Alice', 'age': 25}
# After adding city: {'name': 'Alice', 'age': 25, 'city': 'London'}
# After changing age: {'name': 'Alice', 'age': 26, 'city': 'London'}
# After update: {'name': 'Alice', 'age': 26, 'city': 'London', 'job': 'Developer', 'country': 'UK'}6. Removing Items
| Method | What It Does | Example |
|---|---|---|
| del dict["key"] | Delete a specific key | del person["age"] |
| .pop("key") | Remove and return the value | age = person.pop("age") |
| .popitem() | Remove last inserted item | last = person.popitem() |
| .clear() | Remove all items | person.clear() |
person = {"name": "Alice", "age": 25, "city": "London"}
print("Start:", person)
# del - delete by key
del person["city"]
print("After del:", person)
# pop - remove and get the value
age = person.pop("age")
print(f"Popped age: {age}")
print("After pop:", person)
# pop with default (safe)
job = person.pop("job", "Not found")
print(f"Popped job: {job}")
# ✅ Expected output:
# Start: {'name': 'Alice', 'age': 25, 'city': 'London'}
# After del: {'name': 'Alice', 'age': 25}
# Popped age: 25
# After pop: {'name': 'Alice'}
# Popped job: Not found7. Checking if a Key Exists
Use in to check if a key exists before accessing it:
person = {"name": "Alice", "age": 25}
# Check if key exists
if "name" in person:
print("Name found:", person["name"])
if "email" in person:
print("Email:", person["email"])
else:
print("Email not found")
# Check if key does NOT exist
if "phone" not in person:
print("Phone number not stored")
# Practical pattern: safe access
key = "city"
if key in person:
print(f"{key}: {person[key]}")
else:
print(f"{key} is not in the dictionary")
# ✅ Expected output:
# Name found: Alice
# Email not found
# Phone number not stored
# city is not in the dictionary8. Looping Through Dictionaries
| Loop Type | What You Get | Syntax |
|---|---|---|
| Keys only | Each key | for key in dict: |
| Values only | Each value | for val in dict.values(): |
| Both | Key and value | for key, val in dict.items(): |
person = {"name": "Alice", "age": 25, "city": "London"}
# Loop through keys (default)
print("Keys:")
for key in person:
print(f" {key}")
# Loop through values
print("\nValues:")
for value in person.values():
print(f" {value}")
# Loop through key-value pairs (most common)
print("\nKey-Value pairs:")
for key, value in person.items():
print(f" {key}: {value}")
# ✅ Expected output:
# Keys:
# name
# age
# city
#
# Values:
# Alice
# 25
# London
#
# Key-Value pairs:
# name: Alice
# age: 25
# city: London🟢 Worked Example: a tiny stock room
Everything from the sections above now lands on one piece of data. Read the comments first, then run it and check each printed line against the code that made it. This is the shape of almost every real dictionary job: create it, look things up safely, change it, then loop over it.
# 🟢 WORKED EXAMPLE — a tiny stock room, start to finish
stock = { # keys are item names (strings), values are quantities (numbers)
"apples": 12,
"bananas": 5,
"cherries": 0,
}
# 1. Look something up. Square brackets need the key to actually exist...
print("Apples in stock:", stock["apples"])
# ...whereas .get() returns a fallback instead of crashing with KeyError.
print("Kiwis in stock:", stock.get("kiwis", 0)) # no "kiwis" key, so you get the 0
# 2. Add a new item just by assigning to a key that is not there yet.
stock["kiwis"] = 7
print("After adding kiwis:", stock)
# 3. Change an existing one exactly the same way. += works because the value is a number.
stock["bananas"] += 3 # 5 + 3
print("Bananas now:", stock["bananas"])
# 4. Remove one. pop() deletes the key AND hands you back the value it removed.
sold_out = stock.pop("cherries")
print("Removed cherries, which had:", sold_out)
# 5. Loop over keys and values together with .items().
print("Full stock list:")
for item, qty in stock.items():
print(f" {item}: {qty}")
# 6. A dictionary can answer questions about itself.
print("Number of different items:", len(stock)) # counts keys
print("Total units on the shelf:", sum(stock.values()))
print("Do we sell apples?", "apples" in stock) # 'in' searches KEYS...
print("Do we sell 12?", 12 in stock) # ...never values, so this is False
# ✅ Expected output:
# Apples in stock: 12
# Kiwis in stock: 0
# After adding kiwis: {'apples': 12, 'bananas': 5, 'cherries': 0, 'kiwis': 7}
# Bananas now: 8
# Removed cherries, which had: 0
# Full stock list:
# apples: 12
# bananas: 8
# kiwis: 7
# Number of different items: 3
# Total units on the shelf: 27
# Do we sell apples? True
# Do we sell 12? False🎯 Your Turn: the café price list
Your go. Everything is written except three small pieces — the parts that are actually about dictionaries. Fill in each ___, run it, and compare with the expected output at the bottom of the file.
# 🎯 YOUR TURN — fill in the blanks marked with ___
prices = {"tea": 120, "coffee": 275, "cake": 340} # prices in pence
# 1) Print the price of coffee. Square brackets take the KEY, not a number.
print("Coffee costs:", prices[___], "pence") # 👉 replace ___ with "coffee" (quotes included)
# 2) Juice is not on the list. Ask for it WITHOUT crashing, falling back to 0.
print("Juice costs :", prices.___("juice", 0), "pence") # 👉 which method takes a fallback?
# 3) Add juice to the menu at 199p by assigning to a brand-new key.
prices[___] = 199 # 👉 replace ___ with "juice"
# Already written for you: print the whole menu, one item per line.
for item, pence in prices.items():
print(f" {item}: {pence}p")
print("Items on the menu:", len(prices))
# ✅ Expected output:
# Coffee costs: 275 pence
# Juice costs : 0 pence
# tea: 120p
# coffee: 275p
# cake: 340p
# juice: 199p
# Items on the menu: 4Line 2 catches nearly everyone: juice is printed as 0 before you add it on the next line, because Python runs the file top to bottom. That is not a bug — it is the order of events.
9. Useful Dictionary Methods
| Method | What It Returns | Example |
|---|---|---|
| .keys() | All keys | person.keys() |
| .values() | All values | person.values() |
| .items() | All key-value pairs | person.items() |
| .get(key) | Value or None | person.get("name") |
| .update(dict2) | Merges dict2 into dict | |
| .copy() | A copy of the dict | new = person.copy() |
| len(dict) | Number of pairs | len(person) |
person = {"name": "Alice", "age": 25, "city": "London"}
# Get all keys
print("Keys:", list(person.keys()))
# Get all values
print("Values:", list(person.values()))
# Get all items as tuples
print("Items:", list(person.items()))
# Count pairs
print(f"Number of items: {len(person)}")
# Make a copy
person_copy = person.copy()
person_copy["name"] = "Bob"
print(f"Original name: {person['name']}")
print(f"Copy name: {person_copy['name']}")
# ✅ Expected output:
# Keys: ['name', 'age', 'city']
# Values: ['Alice', 25, 'London']
# Items: [('name', 'Alice'), ('age', 25), ('city', 'London')]
# Number of items: 3
# Original name: Alice
# Copy name: Bob10. Nested Dictionaries
Dictionaries can contain other dictionaries (or lists) as values. This is useful for organizing complex data.
# Nested dictionary - users with details
users = {
"user1": {
"name": "Alice",
"age": 25,
"email": "[email protected]"
},
"user2": {
"name": "Bob",
"age": 30,
"email": "[email protected]"
}
}
# Access nested values
print("User1 name:", users["user1"]["name"])
print("User2 email:", users["user2"]["email"])
# Loop through nested dict
print("\nAll users:")
for user_id, info in users.items():
print(f" {user_id}: {info['name']} ({info['age']})")
# ✅ Expected output:
# User1 name: Alice
# User2 email: [email protected]
#
# All users:
# user1: Alice (25)
# user2: Bob (30)11. Dictionary Comprehension (Advanced)
Like list comprehension, you can create dictionaries in one line:
# Create a dictionary of squares
squares = {x: x**2 for x in range(1, 6)}
print("Squares:", squares)
# Create from two lists
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
people = {name: age for name, age in zip(names, ages)}
print("People:", people)
# With condition
even_squares = {x: x**2 for x in range(10) if x % 2 == 0}
print("Even squares:", even_squares)
# ✅ Expected output:
# Squares: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# People: {'Alice': 25, 'Bob': 30, 'Charlie': 35}
# Even squares: {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}12. Common Mistakes to Avoid
| Mistake | Problem | Solution |
|---|---|---|
| Accessing missing key | dict["missing"] | Use .get() or check with in |
| Using list as key | Keys must be immutable (str, int, tuple) | |
| Using square brackets | ["key", "value"] | Use curly braces |
| Forgetting the colon | Use | |
| Duplicate keys | Each key must be unique (last value wins) |
13. Practical Examples
Example 1: User Profile
# Store user information
user = {
"username": "alice123",
"email": "[email protected]",
"age": 25,
"is_verified": True
}
# Display profile
print("=== User Profile ===")
for key, value in user.items():
print(f"{key}: {value}")
# Update email
user["email"] = "[email protected]"
print(f"\nUpdated email: {user['email']}")
# ✅ Expected output:
# === User Profile ===
# username: alice123
# email: [email protected]
# age: 25
# is_verified: True
#
# Updated email: [email protected]Example 2: Word Counter
# Count word occurrences
text = "apple banana apple cherry banana apple"
words = text.split()
word_count = {}
for word in words:
if word in word_count:
word_count[word] += 1
else:
word_count[word] = 1
print("Word counts:")
for word, count in word_count.items():
print(f" {word}: {count}")
# ✅ Expected output:
# Word counts:
# apple: 3
# banana: 2
# cherry: 1Example 3: Simple Contact Book
# Contact book
contacts = {
"Alice": "123-456-7890",
"Bob": "234-567-8901",
"Charlie": "345-678-9012"
}
# Look up a contact
name = "Bob"
if name in contacts:
print(f"{name}'s number: {contacts[name]}")
else:
print(f"{name} not found")
# Add new contact
contacts["Diana"] = "456-789-0123"
# List all contacts
print("\nAll contacts:")
for name, phone in contacts.items():
print(f" {name}: {phone}")
# ✅ Expected output:
# Bob's number: 234-567-8901
#
# All contacts:
# Alice: 123-456-7890
# Bob: 234-567-8901
# Charlie: 345-678-9012
# Diana: 456-789-0123🏁 Mini-Challenge: count the votes
No blanks this time — just the brief and an empty outline. You have a list of votes with repeats in it. Turn it into a dictionary of vote counts, print each candidate on its own line in the order they first appear, then announce the winner.
The whole trick is one line inside the loop: counts[vote] = counts.get(vote, 0) + 1 reads "whatever this name is on so far (0 if it is new), plus one". Try to get there yourself before you read that again.
# 🏁 MINI-CHALLENGE — write it yourself
votes = ["ana", "ben", "ana", "cara", "ana", "ben"]
# 1. Start with an empty dictionary called counts.
# 2. Loop over votes. For each name, add 1 to its entry in counts.
# Careful: the first time you see a name it has no entry yet,
# so .get(name, 0) is safer than counts[name].
# 3. Loop over counts.items() and print "name: number", one per line.
# 4. Find the winner. max(counts, key=counts.get) gives the key with
# the biggest value — then print the name and its count.
# your code here
# ✅ Expected output:
# ana: 3
# ben: 2
# cara: 1
# Winner: ana with 3 votesSummary: Quick Reference
| Operation | Syntax | Example |
|---|---|---|
| Create | ||
| Access (unsafe) | dict["key"] | person["name"] |
| Access (safe) | dict.get("key") | person.get("name") |
| Add/Change | dict["key"] = val | person["age"] = 25 |
| Remove | del dict["key"] | del person["age"] |
| Check exists | "key" in dict | "name" in person |
| Loop | for k, v in dict.items(): | for k, v in person.items(): |
| Length | len(dict) | len(person) |
Lesson done — you can now model real-world data in Python!
Dictionaries are how Python stores structured data — user profiles, API responses, config settings. You know how to create, access, update, loop, and nest them safely.
Practice quiz
How does a dictionary store data?
- By index position
- In key-value pairs
- As a sorted set
- As a fixed tuple
Answer: In key-value pairs. Dictionaries store data as key-value pairs, accessed by key name.
Which brackets create a dictionary?
- [ ]
- ( )
- { }
- < >
Answer: { }. Dictionaries use curly braces, e.g. {"name": "Alice"}.
What happens when you access a missing key with dict['missing']?
- Returns None
- Returns 0
- Raises a KeyError
- Adds the key
Answer: Raises a KeyError. Square-bracket access on a missing key raises a KeyError.
What does person.get('email', 'N/A') return if 'email' is missing?
- None
- 'N/A'
- KeyError
- Empty string
Answer: 'N/A'. .get() returns the supplied default ('N/A') when the key is absent.
How do you add a new key 'age' with value 25 to dict person?
- person.add('age', 25)
- person['age'] = 25
- person.append(25)
- person.insert('age', 25)
Answer: person['age'] = 25. Assigning to a new key, person['age'] = 25, adds the pair.
Which loop gives you both keys and values?
- for k in dict:
- for v in dict.values():
- for k, v in dict.items():
- for i in dict.keys():
Answer: for k, v in dict.items():. .items() yields (key, value) pairs you can unpack in the loop.
Can a list be used as a dictionary key?
- Yes, always
- No, keys must be immutable
- Only if it's empty
- Only with .get()
Answer: No, keys must be immutable. Keys must be immutable (str, int, tuple); a list raises a TypeError.
What does {x: x**2 for x in range(1, 6)} create?
- {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
- {1, 4, 9, 16, 25}
- [1, 4, 9, 16, 25]
- {0: 0, 1: 1, ...}
Answer: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}. The dict comprehension maps each x (1-5) to its square.
If a dictionary literal has a duplicate key {'a': 1, 'a': 2}, what is the value of 'a'?
- 1
- 2
- Error
- [1, 2]
Answer: 2. Keys are unique; the last value wins, so 'a' is 2.
What does len() return for {'name': 'Alice', 'age': 25, 'city': 'London'}?
- 2
- 3
- 6
- 1
Answer: 3. len() counts the number of key-value pairs: 3.
Continue this course
- Previous: Lists and Collections
- Next: *args & **kwargs — Accept any number of positional and keyword arguments in your functions
- Quick reference: Python cheat sheet › Collections