Key-Value Storage With Dictionaries
Dictionaries are Python's most important data structure after lists — they map keys to values, deliver O(1) lookup, and back nearly every internal Python feature (namespaces, class attributes, JSON objects). This chapter explores creation, methods, iteration, comprehensions, and the design patterns that make dictionaries unbeatable.
Overview
Fast Lookup
Average O(1) retrieve by key — essential for caches & indexes.
Any Hashable Key
Strings, integers, tuples — even custom objects with __hash__.
Ordered (3.7+)
Items are returned in insertion order.
Nestable
Build trees, configs, and JSON-like structures by nesting dicts.
Comprehensions
Build or transform dictionaries in one expressive line.
Syntax
- Create with
{}ordict(). - Access with
d[key]or safely withd.get(key, default). - Mutate with assignment
d[key] = value,update(), orpop(). - Iterate over
keys(),values(), oritems().
user = {
"name": "Riya",
"age": 22,
"skills": ["Python", "SQL"],
}
print(user["name"])
print(user.get("email", "n/a"))
user["age"] = 23 # update
user.setdefault("city", "Pune") # add if missing
del user["skills"] # remove
for k, v in user.items():
print(k, "=>", v)
Detailed Explanation
- Hash-table magic: Dictionaries use a hash table — average
O(1)lookup, insertion, and deletion. The key's__hash__determines its slot. - Keys must be hashable: Immutable types (str, int, float, tuple of immutables) can be keys. Lists and dicts cannot — they raise
TypeError. - Common methods:
get(key, default),keys(),values(),items(),update(other),pop(key),setdefault(key, default). - Iteration: Iterating a dict yields keys. Use
.items()for key-value pairs,.values()for values. - Dictionary comprehensions:
{k: v for k, v in pairs if cond}— compact and idiomatic. Great for transforming/inverting dictionaries. - Merging dictionaries: Python 3.9+ allows
a | bto merge two dicts, with b's values winning on conflict.
Code Examples
student = {"name": "Anu", "marks": 92}
print(student["name"])
print(student.get("dob", "unknown"))
unknown
d = {"a": 1, "b": 2}
d["c"] = 3
d.update(a=10, d=4)
del d["b"]
print(d)
inventory = {"apple": 50, "banana": 20, "cherry": 35}
for fruit, qty in inventory.items():
print(f"{fruit:8s} {qty}")
banana 20
cherry 35
squares = {x: x*x for x in range(1, 6)}
print(squares)
text = "to be or not to be"
freq = {}
for w in text.split():
freq[w] = freq.get(w, 0) + 1
print(freq)
a = {"x": 1, "y": 2}
b = {"y": 20, "z": 30}
print(a | b)
Real-World Use Cases
User Profiles
Each user is a dict of name, email, preferences.
JSON Data
Every JSON object maps 1-to-1 to a Python dict.
Lookup Caches
Memoise expensive function results in a dict keyed by inputs.
Configuration
App settings stored as nested dicts.
Counters
Track occurrences of words, events, or errors.
Grade Books
Map student-id → record (name, subject, marks).
Notes & Pro Tips
- Use
.get(key, default)to avoidKeyError. - Use
collections.defaultdictfor auto-creating missing values. - Use
collections.Counterfor frequency counting. - Dictionary keys must be hashable — strings and tuples are perfect.
- Iterate with
.items()for both keys and values. - JSON ↔ dict conversion:
json.dumps(d)andjson.loads(s).
Common Mistakes
- Modifying during iteration: raises
RuntimeError— copy keys first. - Using a mutable as key: lists and dicts can't be keys.
- Accessing missing key with
d[k]: raisesKeyError; useget. - Confusing
updatewith new dict:updatemutates in place. - Hash collisions on bad
__hash__: custom classes need consistent hash + eq. - Assuming order before 3.7: not guaranteed in older Python.
Practice Problems
- Problem 1: Build a phonebook that supports add, search, update, and delete.
- Problem 2: Count the frequency of each character in a string using a dictionary.
- Problem 3: Invert a dictionary so keys become values and vice versa.
- Problem 4: Read a list of (name, marks) tuples and create a dict mapping names to marks.
- Problem 5: Group a list of words by their first letter into a dictionary of lists.
- Problem 6: Find the key with the maximum value in a dictionary.
Interview Questions
- Q1. What is a dictionary in Python? What is its underlying data structure?
- Q2. What types can be dictionary keys?
- Q3. What is the time complexity of dictionary operations?
- Q4. Difference between
dict.get(k)anddict[k]? - Q5. How would you merge two dictionaries in Python 3.9+?
- Q6. What is the difference between
dictandcollections.OrderedDicttoday?
Frequently Asked Questions
- Q1: Are dictionaries ordered?
Since Python 3.7, yes — they preserve insertion order. Earlier versions did not guarantee it. - Q2: How do I safely look up a key?
Use d.get(key, default). It returns default (or None) when the key is missing instead of raising KeyError. - Q3: Can I use a list as a key?
No — lists are mutable and not hashable. Use a tuple if you need a composite key. - Q4: How do I merge two dicts?
Python 3.9+: a | b. Older versions: {**a, **b} or a.update(b). - Q5: What is a defaultdict?
A dict subclass from collections that auto-creates a default value (e.g. an empty list) when a missing key is accessed. - Q6: How do I convert JSON to a dict?
Use json.loads(json_string). Use json.dumps(dict_obj) for the reverse.
Summary
Dictionaries are the workhorse of fast Python lookup. They power JSON, caching, configuration, counting, indexing, and much of the language itself. Master the core methods, the comprehension syntax, and friends like defaultdict and Counter — and you'll write Python that reads like clear English and runs at hash-table speed.
Continue Learning
Previous
Go to Previous Chapter