Dictionaries are Python's most versatile data structure. Here is how to use them well.
Basic Operations
# Create
d = {"name": "Owen", "age": 25}
d = dict(name="Owen", age=25)
# Access
d["name"] # "Owen"
d.get("name") # "Owen"
d.get("missing", "default") # "default"
# Add or update
d["email"] = "owen@example.com"
d.update({"city": "NYC", "age": 26})
# Delete
del d["age"]
value = d.pop("email") # Returns and removes
d.clear() # Remove allSafe Access with get
user = {"name": "Owen"}
# Risky - raises KeyError if missing
user["email"]
# Safe - returns None or default
user.get("email")
user.get("email", "no email")Always use get when the key might not exist.
setdefault
Get value if exists, set and return default if not:
counts = {}
# Instead of this
if "apple" not in counts:
counts["apple"] = 0
counts["apple"] += 1
# Use setdefault
counts.setdefault("apple", 0)
counts["apple"] += 1
# Or for lists
groups = {}
groups.setdefault("fruit", []).append("apple")Iteration
d = {"a": 1, "b": 2, "c": 3}
# Keys
for key in d:
print(key)
for key in d.keys():
print(key)
# Values
for value in d.values():
print(value)
# Both
for key, value in d.items():
print(key, value)Dictionary Comprehensions
# Basic
squares = {x: x**2 for x in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# With condition
evens = {x: x**2 for x in range(10) if x % 2 == 0}
# From two lists
keys = ["a", "b", "c"]
values = [1, 2, 3]
d = {k: v for k, v in zip(keys, values)}
# Swap keys and values
original = {"a": 1, "b": 2}
swapped = {v: k for k, v in original.items()}Merging Dictionaries
d1 = {"a": 1, "b": 2}
d2 = {"b": 3, "c": 4}
# Python 3.9+
merged = d1 | d2 # {"a": 1, "b": 3, "c": 4}
# Update in place
d1 |= d2
# Earlier versions
merged = {**d1, **d2}Later values override earlier ones.
Sorting
d = {"banana": 3, "apple": 1, "cherry": 2}
# By keys
sorted(d.items())
# [("apple", 1), ("banana", 3), ("cherry", 2)]
# By values
sorted(d.items(), key=lambda x: x[1])
# [("apple", 1), ("cherry", 2), ("banana", 3)]
# Create sorted dict
dict(sorted(d.items(), key=lambda x: x[1]))Check Existence
d = {"a": 1, "b": 2}
# Check key
"a" in d # True
"c" in d # False
# Check value
1 in d.values() # TrueDefault Values with defaultdict
from collections import defaultdict
# Instead of setdefault everywhere
counts = defaultdict(int)
counts["apple"] += 1 # No KeyError
groups = defaultdict(list)
groups["fruit"].append("apple")Nested Dictionaries
users = {
"user1": {"name": "Owen", "age": 25},
"user2": {"name": "Alex", "age": 30}
}
# Access nested value
users["user1"]["name"]
# Safe nested access
def get_nested(d, *keys, default=None):
for key in keys:
if isinstance(d, dict):
d = d.get(key, default)
else:
return default
return d
get_nested(users, "user1", "name") # "Owen"
get_nested(users, "user3", "name") # NoneCommon Patterns
Count occurrences
from collections import Counter
words = ["apple", "banana", "apple", "cherry"]
counts = Counter(words)
# Counter({"apple": 2, "banana": 1, "cherry": 1})Group by key
from collections import defaultdict
items = [
{"type": "fruit", "name": "apple"},
{"type": "vegetable", "name": "carrot"},
{"type": "fruit", "name": "banana"},
]
grouped = defaultdict(list)
for item in items:
grouped[item["type"]].append(item["name"])Invert dictionary
original = {"a": 1, "b": 2, "c": 3}
inverted = {v: k for k, v in original.items()}
# {1: "a", 2: "b", 3: "c"}Filter dictionary
d = {"a": 1, "b": 2, "c": 3, "d": 4}
filtered = {k: v for k, v in d.items() if v > 2}
# {"c": 3, "d": 4}Performance
- Access by key: O(1)
- Check existence: O(1)
- Iteration: O(n)
Dictionaries are hash tables. Key lookup is fast regardless of size.
Dictionaries are essential. Learn these patterns and you will write cleaner Python.
React to this post: