Python Dictionaries
Introduction: Purpose and Value of Python Dictionaries
Python dictionaries are fundamental, versatile, and powerful data structures essential
for both novice and advanced Python programmers. They allow for the storage and fast
retrieval of data using a key-value paradigm, making them suitable for a vast range of
applications-from simple mappings like phonebooks to complex representations of
nested, hierarchical data. Understanding dictionaries is critical for learners attempting
data processing, configuration management, machine learning, or web development, as
well as for daily coding tasks1. This guide offers comprehensive, educator-friendly
explanations, examples, best practices, and exercises covering every major aspect of
Python dictionaries, based on authoritative tutorials and the latest learning resources.
1. Python Dictionary Overview and Definition
Dictionaries in Python are built-in data types for storing collections of key-value pairs.
Each key in a dictionary maps to a specific value, and keys must be immutable and
unique. Dictionaries are mutable (modifiable), unordered before Python 3.7 but
guaranteed ordered by insertion from Python 3.7 onwards, and permit heterogeneous
types for both keys (if immutable) and values2.
Key properties:
Unordered (prior to Python 3.7), Ordered (Python 3.7+): Items have no fixed
order in earlier versions, but later versions keep insertion order.
Mutable: Dictionaries can be changed after creation-items can be added, modified,
or removed.
No duplicate keys: Assigning to an existing key overwrites the value.
Keys must be unique and immutable types: Valid keys are strings, numbers,
tuples (if their contents are immutable).
Values can be of any data type: Including strings, numbers, lists, other
dictionaries, or user-defined objects.
Syntax: Dictionaries use curly braces {} with key-value pairs separated by colons
and pairs separated by commas.
Examples:
# Simple dictionary
person = {'name': 'John', 'age': 30, 'city': 'New York'}
print(person)
# Output: {'name': 'John', 'age': 30, 'city': 'New York'}
# Dictionary with different key/value types
data = {1: 'number key', (2, 3): 'tuple as key', 'active': True}
In dictionaries, the colon : separates keys from values, and each key-value pair is
separated by a comma2.
2. Accessing Dictionary Items
Accessing items in a dictionary can be done using keys, the get() method, or by
iterating over the dictionary. Understanding these methods is fundamental for retrieving
and using stored data.
2.1 Using Square Brackets ([])
Syntax: dict[key]
Raises KeyError if the key does not exist.
Example:
capitals = {"Maharashtra": "Mumbai", "Gujarat": "Gandhinagar", "Karnataka":
"Bengaluru"}
print("Capital of Gujarat:", capitals['Gujarat'])
# Output: Capital of Gujarat: Gandhinagar
If you attempt capitals['Haryana'], it will raise a KeyError34.
2.2 Using the get() Method
Syntax: dict.get(key, default_value)
Returns: The value for key if present, otherwise None or a specified
default_value.
Does not raise an exception if the key is missing, making it safer for uncertain key
lookups.
Example:
print("Capital of Haryana:", capitals.get('Haryana', 'Not found'))
# Output: Capital of Haryana: Not found
2.3 Accessing All Keys, Values, or Items
keys(): Returns a view object of all keys in the dictionary.
values(): Returns a view object of all values.
items(): Returns a view object of all key-value pairs as tuples.
Example:
my_dict = {"name": "Alice", "age": 21, "major": "CS"}
print(my_dict.keys()) # dict_keys(['name', 'age', 'major'])
print(my_dict.values()) # dict_values(['Alice', 21, 'CS'])
print(my_dict.items()) # dict_items([('name', 'Alice'), ('age', 21),
('major', 'CS')])
These “views” update automatically when the dictionary changes56.
2.4 Checking If a Key Exists
Use the in keyword: if key in dict:
Returns True if the key exists.
Example:
if 'age' in my_dict:
print('Age is in the dictionary')
3. Modifying and Changing Dictionary Items
Dictionary items can be modified using assignment or specialized methods. Changes
can affect individual or multiple entries.
3.1 Updating a Value
Assign a new value to an existing key: dict[key] = new_value
Overwrites the previous value.
Example:
person = {'name': 'Alice', 'age': 25}
person['age'] = 26
print(person)
# Output: {'name': 'Alice', 'age': 26}
3.2 Updating Multiple Values with update()
Syntax: dict.update(other_dict_or_kv_pairs)
Updates keys or adds new keys with the given values.
Example:
person.update({'age': 27, 'city': 'Los Angeles'})
# Now person is {'name': 'Alice', 'age': 27, 'city': 'Los Angeles'}
Also accepts keyword arguments: person.update(city='Boston',
job='Engineer')
3.3 Conditional Modification
Modify a value only if a certain condition is met using a simple if statement.
Example:
if person['age'] == 27:
person['eligible'] = True
4. Adding Items to a Dictionary
Adding new key-value pairs is straightforward, and several methods exist to add one or
many pairs at once.
4.1 Using Assignment with Square Brackets
Assigning a value to a new key: dict[new_key] = value
If the key already exists, it updates the value; else, a new key-value pair is created.
Example:
info = {'name': 'Karan', 'age': 19}
info['DOB'] = 2001
# Now info is {'name': 'Karan', 'age': 19, 'DOB': 2001}
4.2 Using update()
Syntax: dict.update({'key': value})
Can update one or many keys.
Example:
info.update({'hometown': 'Delhi', 'gender': 'Male'})
4.3 Using setdefault()
Adds a key with a default value if it does not exist. Returns the value for that key.
Example:
d = {}
d.setdefault('new_key', 100) # Adds 'new_key': 100
4.4 Dictionary Unpacking and Union Operator (Python 3.5+/3.9+)
Merging two or more dictionaries with {**dict1, **dict2} or dict1 | dict2
(3.9+).
Example:
a = {'x': 1}
b = {'y': 2, 'z': 3}
c = {**a, **b}
# c = {'x': 1, 'y': 2, 'z': 3}
# Python 3.9+
c = a | b
5. Removing Items from a Dictionary
Removing items is essential for managing memory and controlling the contents of
dictionaries. Python provides multiple ways to remove specific or all items, each suitable
for different scenarios.
5.1 del Keyword
Syntax: del dict[key]
Removes a key-value pair by key. Raises KeyError if key does not exist.
Example:
person = {'name': 'Karan', 'age': 19, 'DOB': 2003}
del person['age']
# Now person is {'name': 'Karan', 'DOB': 2003}
del dict deletes the entire dictionary; accessing it afterwards raises NameError.
5.2 pop() Method
Removes a key and returns its value.
Syntax: dict.pop(key[, default])
o If the key is missing and default is not provided, raises KeyError.
o If default is provided, returns default instead.
Example:
val = person.pop('DOB')
# val = 2003, person now {'name': 'Karan'}
5.3 popitem() Method
Removes and returns the last inserted key-value pair (in Python 3.7+, prior versions
remove an arbitrary pair).
Syntax: dict.popitem()
Returns a tuple (key, value). Raises KeyError if the dictionary is empty.
Example:
d = {'a': 1, 'b': 2}
key, value = d.popitem()
5.4 clear() Method
Removes all items from the dictionary, leaving it empty.
Example:
d.clear()
print(d) # Output: {}
6. Dictionary View Objects (keys(), values(), items())
Python’s view objects (dict_keys, dict_values, dict_items) provide dynamic,
memory-efficient read-only windows onto a dictionary’s keys, values, or items. They
automatically reflect changes to the dictionary56.
6.1 Properties and Usage
Dynamic: Views change as the dictionary changes.
Efficient: Do not copy the data; lightweight proxy objects.
Set-like: dict_keys and dict_items support set operations.
Can be converted to lists or tuples if a static snapshot is needed.
Example:
d = {'a': 1, 'b': 2}
keys_view = d.keys()
d['c'] = 3
print(keys_view) # Now shows dict_keys(['a', 'b', 'c'])
Common Operations:
len(d.keys())
"a" in d.keys()
list(d.keys())
Iteration: for key in d.keys(): ...
Pitfall: Modifying the dictionary during iteration over a view raises a RuntimeError.
7. Looping and Iterating Through Dictionaries
Looping through a dictionary is crucial for performing batch operations, processing data,
or constructing output.
7.1 Iterating Over Keys (default)
Syntax:
for key in dict:
print(key, dict[key])
7.2 Iterating Over Keys Explicitly
Use .keys() for clarity:
for key in dict.keys():
print(key)
7.3 Iterating Over Values
Use .values():
for value in dict.values():
print(value)
7.4 Iterating Over Items
Use .items(), which gives both key and value per iteration:
for key, value in dict.items():
print(key, value)
7.5 Iterating in Nested Dictionaries
Nest loops as needed:
people = {'Alice': {'age': 21, 'major': 'CS'}, 'Bob': {'age': 20, 'major':
'Math'}}
for name, info in people.items():
for k, v in info.items():
print(f"{name} - {k}: {v}")
8. Copying Dictionaries (Shallow vs Deep Copies)
Copying is a common operation when you need an independent duplicate of dictionary
data.
8.1 Assignment Is Not Copying
dict2 = dict1 results in dict2 and dict1 referring to the same object.
Changing one affects the other78.
8.2 Shallow Copy
copy(): new_dict = old_dict.copy()
dict(): new_dict = dict(old_dict)
Dictionary comprehension: new_dict = {k: v for k, v in
old_dict.items()}
Only the top-level dictionary is copied. Nested objects (lists, dicts) are still shared.
Example:
original = {'a': 1, 'b': [2, 3]}
shallow = original.copy()
shallow['b'].append(4)
# Both 'original' and 'shallow' now have 'b': [2, 3, 4]
8.3 Deep Copy
copy.deepcopy(): Recursively copies all nested objects, creating a completely
independent copy.
Example:
import copy
original = {'a': 1, 'b': [2, 3]}
deep = copy.deepcopy(original)
deep['b'].append(4)
# Only 'deep' has 'b': [2, 3, 4]; 'original' remains unmodified
9. Nested Dictionaries and Multi-level Access
A nested dictionary is one where values themselves are dictionaries. They allow you to
model complex, hierarchical, or grouped data logically.
9.1 Creating Nested Dictionaries
Direct assignment:
students = {
"Alice": {"age": 21, "major": "CS"},
"Bob": {"age": 20, "major": "Engineering"}
}
Dynamic construction:
nested = {}
nested['outer1'] = {"inner1": "value1"}
9.2 Accessing Nested Items
Use a chain of keys:
major = students["Alice"]["major"] # "CS"
Use .get() with default values for safety:
major = students.get("Alice", {}).get("major", "Not Found")
9.3 Modifying Nested Structures
Add a new inner attribute:
students["Alice"]["GPA"] = 3.8
Add a new nested dictionary:
students["Charlie"] = {"age": 22, "major": "Mathematics"}
Delete an inner key or entire inner dictionary:
del students["Alice"]["major"]
del students["Bob"]
9.4 Iterating Through Nested Dictionaries
Double loop:
for name, info in students.items():
print(f"{name}:")
for key, value in info.items():
print(f" {key}: {value}")
10. Comprehensive List of Dictionary Methods
The Python dictionary object provides a suite of built-in methods for data manipulation
and access.
Method Description Example Usage
clear() Removes all items d.clear()
copy() Returns a shallow copy d2 = d.copy()
Creates dict from seq of keys, assigns them a given default
fromkeys() dict.fromkeys([a,b,c], 0)
value
get() Returns value for key, or default if not found d.get('k', default)
items() Returns view of (key, value) pairs for k,v in d.items():
keys() Returns view of keys for k in d.keys():
pop() Removes key and returns its value d.pop('k')
popitem() Removes/returns last inserted key-value pair (as tuple) k,v = d.popitem()
setdefault(
Sets value if key does not exist, returns value d.setdefault('k', val)
)
d.update({'new':
update() Updates with another dict or iterable of key-values
'value'})
values() Returns view of values for v in d.values():
Detailed explanations for educators:
clear(): Empties the dictionary.
copy() / dict(): Creates a shallow copy, i.e., only the top level is duplicated.
fromkeys(): Useful for initializing a dictionary with specific keys and identical values.
get(): Safely retrieves a value; ideal to avoid KeyError.
items(), keys(), values(): Efficient dynamic views; best for loops and set operations.
pop(): Deletes a given key, returns value.
popitem(): Removes and returns the most recently inserted key-value pair.
setdefault(): Great for grouping, e.g., initializing a key with a list for appending.
update(): Merges or adds/updates multiple entries.
values(): Efficiently previews all values.
11. Table: Key Python Dictionary Methods and Their Uses
Method Description Typical Use Case
Remove all items, dictionary is now
clear() Resetting data storage
empty
Create template/backup before
copy() Make a shallow copy of dictionary
changes
fromkeys(seq, Create dict from keys in a sequence
Initialize config/status flags
value) with the same value
get(key,
Return value for key, else default value Safe lookup without exception
default=None)
Iterate all entries for
items() Return view of (key, value) tuple pairs
display/process
Quick membership tests,
keys() Return view of all keys
reporting headers
Remove and return value for key, else
pop(key[, default]) Delete-and-fetch for processing
default/KeyError
Remove and return latest key-value
popitem() Stack-like latest-out removal
pair
setdefault(key, Returns key value; if key is missing, Grouping values, initializing
value) inserts with value structures
update([other| Update dictionary with another Merge configs, add/update
pairs]) dict/iterable of pairs several entries
values() Return view of all values Statistics, analysis, output data
12. Common Pitfalls and Errors with Dictionaries
12.1 KeyError
Cause: Accessing an absent key with square brackets dict[key].
How to avoid: Use .get(), or check presence with in before access.
12.2 Reference Copy Issues
dict2 = dict1 binds both names to the same object. Changes on one propagate
to the other.
For independent objects, always use dict.copy() or dict(); for nested data,
use copy.deepcopy().
12.3 Syntax Errors
Use colon : between key and value in definitions.
Use commas between pairs.
Keys must be immutable; using mutable types (like lists) causes TypeError.
12.4 Modifying While Iterating
Modifying a dictionary while iterating through its keys/items can raise a
RuntimeError. To safely alter, iterate over a static snapshot, e.g.,
list(d.keys()) or tuple(d.items()).
12.5 Copying Nested Dictionaries (Shallow vs Deep Copy Confusion)
Shallow copy (copy()/dict()) copies only the outer dictionary, sharing references
for values. Mutating nested/mutable values affects both copies.
Deep copy (copy.deepcopy()) duplicates nested mutable objects too. Use for
total independence97.
13. Summary Table of Key Dictionary Concepts
Concept Syntax/Code Example Notes
Creation d = {"a": 1, "b": 2} Use curly braces
Access d["a"], d.get("a", default) get() avoids KeyError
Insert/Update d["c"] = 3, d.update({"d": 4}) Updates or inserts
Delete One del d["a"], d.pop("b") del or pop()
Delete All d.clear() Empties dict
Loop Keys/Values for k in d:, for v in d.values(): For display or processing
Copy new = d.copy(), deepcopy(d) Shallow vs deep copy
Nested d["nested"]["key"] Multi-level access
Methods d.keys(), d.values(), d.items() Dynamic views
Comprehension {k:v for k,v in seq} Compact dict creation/tranform