Python Dictionaries
Dictionaries
A dictionary stores data as key–value pairs. Each key is a unique identifier, and each key is linked to a value. Instead of finding data by its position (as with lists), you find it by its name.
Think of a real dictionary: you look up a word (the key) to find its definition (the value). In Python:
student = {"name": "Amit", "course": "Python"}
print(student["name"])
Expected output:
Amit
Dictionaries are everywhere in real Python programs: user profiles, configuration settings, product records, counting word frequencies, and JSON data from web APIs all map naturally to dictionaries.
Dictionary Characteristics
A dictionary is:
- Ordered — items keep their insertion order (guaranteed from Python 3.7 onwards).
- Changeable (mutable) — items can be added, modified, and removed after creation.
- Unique keys — duplicate keys are not allowed.
Python's Collection Types Compared
| Collection | Ordered | Changeable | Duplicates |
|---|---|---|---|
| List | Yes | Yes | Allowed |
| Tuple | Yes | No | Allowed |
| Set | No | Items cannot be changed, but can be added or removed | Not allowed |
| Dictionary | Yes (Python 3.7+) | Yes | No duplicate keys |
Creating a Dictionary
Dictionaries are created with curly braces { }. Each item is written as key: value, and items are separated by commas.
student = {
"name": "Amit",
"course": "Python",
"duration": 6
}
print(student)
Expected output:
{'name': 'Amit', 'course': 'Python', 'duration': 6}
Writing each item on its own line, as above, makes larger dictionaries easier to read.
What Can Be a Key?
- Keys must be immutable (hashable) values: strings, numbers, booleans, or tuples of immutable values.
- Strings are by far the most common key type.
- Lists and other dictionaries cannot be keys.
Values have no restrictions — they can be any data type.
Dictionary Items
Each item consists of a key and a value. You access a value by referring to its key.
student = {
"name": "Amit",
"course": "Python",
"duration": 6
}
print(student["course"])
Expected output:
Python
Ordered vs Unordered
- From Python 3.7 onward, dictionaries keep items in the order they were inserted.
- In Python 3.6 and earlier, the order of items was not guaranteed by the language.
Ordered means items stay in the sequence they were added, so printing or looping always produces the same order.
Note: Even though dictionaries are ordered, you still cannot access items by a numeric position such as
student[0]. Items are accessed by key.student[0]looks for a key named0and raises aKeyErrorif there isn't one.
Changing Dictionary Data
Dictionaries are mutable, so you can add, modify, or remove items after creation.
student = {
"name": "Amit",
"course": "Python",
"duration": 6
}
student["duration"] = 8
print(student)
Expected output:
{'name': 'Amit', 'course': 'Python', 'duration': 8}
Duplicate Keys Are Not Allowed
A dictionary cannot contain two items with the same key. If a key appears more than once, the last value replaces the earlier one.
car = {
"brand": "Tesla",
"year": 2019,
"year": 2023
}
print(car)
Expected output:
{'brand': 'Tesla', 'year': 2023}
Python does not raise an error — it silently keeps the last value. Watch for this when building dictionaries by hand.
Values, on the other hand, can repeat: {"a": 1, "b": 1} is perfectly valid.
Dictionary Length
Use len() to count the key–value pairs.
languages = {
"first": "Python",
"second": "Java",
"third": "C++"
}
print(len(languages))
Expected output:
3
Dictionary Values and Data Types
Values can be of any type — strings, numbers, booleans, lists, or even other dictionaries.
product = {
"name": "Laptop",
"price": 65000,
"available": True,
"features": ["SSD", "8GB RAM", "i5 Processor"]
}
print(product["features"][0])
Expected output:
SSD
product["features"] returns the list, and [0] selects its first item.
Checking the Dictionary Data Type
product = {
"name": "Laptop",
"price": 65000
}
print(type(product))
Expected output:
<class 'dict'>
Using the dict() Constructor
The dict() constructor creates a dictionary using keyword arguments.
profile = dict(username="max123", followers=1200, verified=False)
print(profile)
Expected output:
{'username': 'max123', 'followers': 1200, 'verified': False}
With keyword arguments, the keys are written without quotes and must be valid Python names. The dict() constructor can also build a dictionary from a list of key–value pairs:
pairs = [("a", 1), ("b", 2)]
print(dict(pairs))
Expected output:
{'a': 1, 'b': 2}
Accessing Dictionary Items
Accessing Values With Square Brackets
employee = {
"id": 101,
"name": "Ravi",
"role": "Developer"
}
result = employee["role"]
print(result)
Expected output:
Developer
If the key does not exist, this raises a KeyError:
print(employee["salary"])
Output:
KeyError: 'salary'
Accessing Values With get()
get() also retrieves a value by key, but it returns None (or a default value you provide) instead of raising an error when the key is missing.
employee = {
"id": 101,
"name": "Ravi",
"role": "Developer"
}
print(employee.get("role"))
print(employee.get("salary"))
print(employee.get("salary", "Not set"))
Expected output:
Developer
None
Not set
When to use which:
- Use
employee["role"]when the key must exist — a missing key indicates a bug, and the error helps you find it. - Use
employee.get("salary", default)when a key is optional.
Getting All Keys With keys()
keys() returns a view object containing all the keys.
employee = {
"id": 101,
"name": "Ravi",
"role": "Developer"
}
keys_list = employee.keys()
print(keys_list)
Expected output:
dict_keys(['id', 'name', 'role'])
Views Update Automatically
A view is a live window into the dictionary, not a copy. When the dictionary changes, the view reflects the change automatically.
employee = {
"id": 101,
"name": "Ravi",
"role": "Developer"
}
keys_list = employee.keys()
print(keys_list) # Before update
employee["salary"] = 50000
print(keys_list) # After update
Expected output:
dict_keys(['id', 'name', 'role'])
dict_keys(['id', 'name', 'role', 'salary'])
keys_list was not reassigned, yet it now includes "salary". If you need a fixed snapshot, convert it to a list: list(employee.keys()).
Getting All Values With values()
employee = {
"id": 101,
"name": "Ravi",
"role": "Developer"
}
values_list = employee.values()
print(values_list)
Expected output:
dict_values([101, 'Ravi', 'Developer'])
The values view also reflects changes — both updated values and newly added items:
employee = {
"id": 101,
"name": "Ravi",
"role": "Developer"
}
values_list = employee.values()
print(values_list) # Before changes
employee["role"] = "Senior Developer"
print(values_list) # After updating a value
employee["experience"] = 5
print(values_list) # After adding an item
Expected output:
dict_values([101, 'Ravi', 'Developer'])
dict_values([101, 'Ravi', 'Senior Developer'])
dict_values([101, 'Ravi', 'Senior Developer', 5])
Getting All Items With items()
items() returns a view of key–value pairs, each represented as a tuple.
employee = {
"id": 101,
"name": "Ravi",
"role": "Developer"
}
items_list = employee.items()
print(items_list)
Expected output:
dict_items([('id', 101), ('name', 'Ravi'), ('role', 'Developer')])
Like the other views, the items view updates automatically:
employee = {
"id": 101,
"name": "Ravi",
"role": "Developer"
}
items_list = employee.items()
employee["role"] = "Team Lead"
employee["location"] = "Bangalore"
print(items_list)
Expected output:
dict_items([('id', 101), ('name', 'Ravi'), ('role', 'Team Lead'), ('location', 'Bangalore')])
Checking Whether a Key Exists
Use the in keyword. It checks keys, not values.
employee = {
"id": 101,
"name": "Ravi",
"role": "Developer"
}
if "role" in employee:
print("Yes, 'role' exists in the employee dictionary")
print("Ravi" in employee)
print("Ravi" in employee.values())
Expected output:
Yes, 'role' exists in the employee dictionary
False
True
"Ravi" is a value, not a key, so "Ravi" in employee is False. To search values, check employee.values().
Changing Dictionary Values
Changing a Value Using Its Key
Assign a new value to an existing key.
product = {
"name": "Smartphone",
"brand": "TechOne",
"price": 18000
}
product["price"] = 15000
print(product)
Expected output:
{'name': 'Smartphone', 'brand': 'TechOne', 'price': 15000}
Updating With update()
update() changes or adds one or more key–value pairs in a single call. Its argument can be:
- Another dictionary
- An iterable of key–value pairs (such as a list of tuples)
Updating a Single Value
product = {
"name": "Smartphone",
"brand": "TechOne",
"price": 18000
}
product.update({"price": 16500})
print(product)
Expected output:
{'name': 'Smartphone', 'brand': 'TechOne', 'price': 16500}
Updating Several Values at Once
product = {
"name": "Smartphone",
"brand": "TechOne",
"price": 18000
}
product.update({"price": 16500, "stock": 40})
print(product)
Expected output:
{'name': 'Smartphone', 'brand': 'TechOne', 'price': 16500, 'stock': 40}
"price" already existed, so its value was replaced; "stock" did not exist, so it was added.
Direct assignment vs update():
- Direct assignment changes one key at a time.
update()can modify or insert many items in one statement — useful when merging data from another source.
Adding Items to a Dictionary
Adding an Item With a New Key
Assigning a value to a key that does not exist yet adds a new item. The same syntax is used for adding and updating.
profile = {
"username": "max_dev",
"followers": 850,
"verified": True
}
profile["bio"] = "Python enthusiast"
print(profile)
Expected output:
{'username': 'max_dev', 'followers': 850, 'verified': True, 'bio': 'Python enthusiast'}
Adding Items With update()
- If the key already exists, its value is updated.
- If the key does not exist, a new item is added.
profile = {
"username": "max_dev",
"followers": 850,
"verified": True
}
profile.update({"location": "India"})
print(profile)
Expected output:
{'username': 'max_dev', 'followers': 850, 'verified': True, 'location': 'India'}
Adding Multiple Items at Once
profile = {
"username": "max_dev",
"followers": 850,
"verified": True
}
profile.update({
"skills": ["Python", "Django"],
"active": True
})
print(profile)
Expected output:
{'username': 'max_dev', 'followers': 850, 'verified': True, 'skills': ['Python', 'Django'], 'active': True}
Removing Items From a Dictionary
1. Removing an Item With pop()
pop() removes the item with the specified key and returns its value.
book = {
"title": "1984",
"author": "George Orwell",
"year": 1949
}
removed_author = book.pop("author")
print(removed_author)
print(book)
Expected output:
George Orwell
{'title': '1984', 'year': 1949}
If the key does not exist, pop() raises a KeyError — unless you provide a default: book.pop("isbn", None).
2. Removing the Last Inserted Item With popitem()
popitem() removes the most recently inserted key–value pair and returns it as a tuple. (Before Python 3.7, an arbitrary item was removed.)
student = {
"name": "Aarav",
"age": 20,
"course": "Computer Science"
}
last_item = student.popitem()
print(last_item)
print(student)
Expected output:
('course', 'Computer Science')
{'name': 'Aarav', 'age': 20}
3. Removing an Item With del
employee = {
"id": 101,
"name": "Riya",
"department": "HR"
}
del employee["department"]
print(employee)
Expected output:
{'id': 101, 'name': 'Riya'}
del does not return the removed value. del employee (without a key) deletes the entire dictionary variable.
4. Removing All Items With clear()
employee = {"id": 101, "name": "Riya"}
employee.clear()
print(employee)
Expected output:
{}
| Tool | Removes | Returns |
|---|---|---|
pop(key) | The item with that key | The value |
popitem() | The last inserted item | A (key, value) tuple |
del dict[key] | The item with that key | Nothing |
clear() | All items | Nothing |
Looping Through a Dictionary
Looping over a dictionary returns its keys by default. The values() and items() methods let you loop over values or over key–value pairs.
All examples in this section use this dictionary:
profile = {
"username": "max_dev",
"followers": 1200,
"active": True
}
1. Looping Through Keys (Default Behavior)
for key in profile:
print(key)
Expected output:
username
followers
active
2. Looping Through Values Using Keys
for key in profile:
print(profile[key])
Expected output:
max_dev
1200
True
3. Looping Through Values With values()
for value in profile.values():
print(value)
Expected output:
max_dev
1200
True
This is cleaner than the previous approach when you only need the values.
4. Looping Through Keys With keys()
for key in profile.keys():
print(key)
The output is the same as example 1. Using keys() simply makes the intent explicit.
5. Looping Through Keys and Values With items()
for key, value in profile.items():
print(key, ":", value)
Expected output:
username : max_dev
followers : 1200
active : True
Each item is a (key, value) tuple, which is unpacked into the two loop variables. This is the most common way to loop through a dictionary.
Caution: Do not add or remove keys while looping over a dictionary. Python raises
RuntimeError: dictionary changed size during iteration. Loop overlist(profile)instead if you need to remove items.
Copying a Dictionary
Assigning a dictionary to another variable with dict2 = dict1 does not create a copy. Both names refer to the same dictionary, so a change through one name is visible through the other.
original = {"name": "Aarav"}
alias = original
alias["name"] = "Changed"
print(original)
Expected output:
{'name': 'Changed'}
To create an independent copy, use one of these methods.
Method 1: Using copy()
student = {
"name": "Aarav",
"age": 20,
"course": "Computer Science"
}
student_backup = student.copy()
student["age"] = 21
print(student)
print(student_backup)
Expected output:
{'name': 'Aarav', 'age': 21, 'course': 'Computer Science'}
{'name': 'Aarav', 'age': 20, 'course': 'Computer Science'}
The backup keeps the original age because it is a separate dictionary.
Method 2: Using the dict() Constructor
product = {
"id": 101,
"name": "Laptop",
"price": 55000
}
product_copy = dict(product)
print(product_copy)
Expected output:
{'id': 101, 'name': 'Laptop', 'price': 55000}
Note: Both methods create a shallow copy. If a value is a list or another dictionary, that inner object is shared between the original and the copy. Use
copy.deepcopy()when you need fully independent nested data.
Nested Dictionaries
A nested dictionary is a dictionary whose values include other dictionaries. Nested dictionaries represent grouped or hierarchical data, such as employees with profiles, students with details, or products with specifications. JSON data from web APIs usually has this shape.
Example 1: Creating a Nested Dictionary Directly
employees = {
"emp1": {
"name": "Ravi",
"department": "HR"
},
"emp2": {
"name": "Anita",
"department": "Finance"
},
"emp3": {
"name": "Kunal",
"department": "IT"
}
}
print(employees["emp3"])
Expected output:
{'name': 'Kunal', 'department': 'IT'}
Example 2: Combining Existing Dictionaries
You can create separate dictionaries first and then place them inside a new dictionary.
book1 = {
"title": "Python Basics",
"price": 499
}
book2 = {
"title": "Data Science Guide",
"price": 899
}
book3 = {
"title": "Web Development",
"price": 699
}
library = {
"book1": book1,
"book2": book2,
"book3": book3
}
Accessing Values in a Nested Dictionary
Chain keys from the outer dictionary inward.
print(library["book2"]["title"])
Expected output:
Data Science Guide
library["book2"] returns the inner dictionary, and ["title"] retrieves its value.
Looping Through a Nested Dictionary
Use items() on the outer dictionary, then again on each inner dictionary.
for book_id, details in library.items():
print(book_id)
for key, value in details.items():
print(" " + key + ":", value)
Expected output:
book1
title: Python Basics
price: 499
book2
title: Data Science Guide
price: 899
book3
title: Web Development
price: 699
How it works:
- The outer loop gives each book's ID (
book_id) and its inner dictionary (details). - The inner loop goes through the keys and values of that inner dictionary.
- The extra spaces in the inner
print()indent the details under each book ID.
Practical Example: Counting Words
Dictionaries are ideal for counting how often things occur.
text = "red blue red green blue red"
counts = {}
for word in text.split():
counts[word] = counts.get(word, 0) + 1
print(counts)
Expected output:
{'red': 3, 'blue': 2, 'green': 1}
counts.get(word, 0) returns the current count, or 0 the first time a word is seen. Adding 1 and storing the result updates the count.
Common Mistakes
| Mistake | Example | Problem |
|---|---|---|
Accessing a missing key with [] | user["email"] | KeyError; use get() for optional keys |
| Using a list as a key | {[1, 2]: "x"} | TypeError: unhashable type: 'list' |
Expecting in to search values | "Ravi" in employee | in checks keys only |
Copying with = | backup = data | Both names share one dictionary |
| Changing size during a loop | del d[k] inside for k in d | RuntimeError |
| Repeating a key by accident | {"a": 1, "a": 2} | The first value is silently lost |
Related Concepts
- Python Dictionary Methods — a complete method reference
- Python JSON — converting between dictionaries and JSON text
- Python Sets — dictionary keys follow the same uniqueness and hashing rules
- Python For Loops — iterating over keys, values, and items