Dictionaries
Dictionaries store key-value pairs with O(1) average lookup. Python 3.7+ guarantees insertion order. Keys must be hashable (strings, numbers, tuples) โ lists can't be keys.
# Creating dicts
empty = {}
person = {"name": "Alice", "age": 30, "city": "NYC"}
from_pairs = dict([("a", 1), ("b", 2)])
from_kwargs = dict(name="Bob", age=25)
# Accessing
person["name"] # "Alice" โ KeyError if missing
person.get("name") # "Alice" โ None if missing
person.get("email", "N/A") # "N/A" โ default value
# Modifying
person["age"] = 31 # Update existing
person["email"] = "alice@example.com" # Add new key
del person["email"] # Remove key
popped = person.pop("age") # Remove + return value
person.pop("missing", None) # Safe pop with default
# Merging (Python 3.9+)
defaults = {"color": "blue", "size": 10}
overrides = {"size": 20, "weight": 5}
merged = defaults | overrides # {'color': 'blue', 'size': 20, 'weight': 5}
defaults |= overrides # In-place mergeIterating Dicts
scores = {"Alice": 95, "Bob": 87, "Carol": 92}
for name in scores: # Keys
print(name)
for score in scores.values(): # Values
print(score)
for name, score in scores.items(): # Key-value pairs
print(f"{name}: {score}")
# Useful
"Alice" in scores # True (checks keys)
95 in scores.values() # True (checks values)
list(scores.keys()) # ['Alice', 'Bob', 'Carol']Dict Patterns
# setdefault โ add key only if not present
d = {}
d.setdefault("count", 0)
d["count"] += 1
# defaultdict โ auto-create missing keys
from collections import defaultdict
# Word frequency counter
text = "the cat sat on the mat the cat"
freq = defaultdict(int)
for word in text.split():
freq[word] += 1
# Group items by category
animals = ["cat", "dog", "crow", "camel", "duck"]
by_letter = defaultdict(list)
for animal in animals:
by_letter[animal[0]].append(animal)
# {'c': ['cat', 'crow', 'camel'], 'd': ['dog', 'duck']}
# Nested dict
config = {
"database": {"host": "localhost", "port": 5432},
"cache": {"host": "redis", "port": 6379}
}
config["database"]["port"] # 5432Sets
Sets are unordered collections of unique hashable elements. O(1) membership test. Perfect for deduplication and set operations.
# Creating sets
empty_set = set() # NOT {} โ that makes a dict!
fruits = {"apple", "banana", "cherry"}
from_list = set([1, 2, 2, 3, 3, 3]) # {1, 2, 3} โ deduplicated
# Membership test
"apple" in fruits # True โ O(1)!
# Adding and removing
fruits.add("date")
fruits.remove("banana") # KeyError if missing
fruits.discard("banana") # No error if missing
popped = fruits.pop() # Remove and return arbitrary elementSet Operations
a = {1, 2, 3, 4, 5}
b = {4, 5, 6, 7, 8}
# Union โ all elements from both
a | b # {1, 2, 3, 4, 5, 6, 7, 8}
a.union(b) # Same
# Intersection โ only common elements
a & b # {4, 5}
a.intersection(b)
# Difference โ in a but not in b
a - b # {1, 2, 3}
a.difference(b)
# Symmetric difference โ in either but not both
a ^ b # {1, 2, 3, 6, 7, 8}
# Subset and superset
{1, 2}.issubset({1, 2, 3}) # True
{1, 2, 3}.issuperset({1, 2}) # True
{1, 2}.isdisjoint({3, 4}) # True (no common elements)
# Deduplication (most common use)
names = ["Alice", "Bob", "Alice", "Carol", "Bob"]
unique = list(set(names)) # Order not guaranteed!
# Preserve order:
seen = set()
unique = [x for x in names if not (x in seen or seen.add(x))]Key Takeaways
- dict.get(key, default): safe access without KeyError
- defaultdict: auto-creates keys โ great for grouping and counting
- Set for membership tests: O(1) vs O(n) for lists
- Set operations: union |, intersection &, difference -, symmetric ^
- empty_set = set(): not
{}โ that's an empty dict!
Practice Exercises
- Write a word frequency counter using defaultdict. Find the 5 most common words.
- Given two lists, find: (a) common elements, (b) elements in list1 but not list2, (c) all unique elements combined.
- Invert a dictionary (swap keys and values). What happens when values aren't unique?
- Write a function that groups a list of words by their first letter, returning a dict of lists.