Dictionary Methods & Comprehensions
Beyond basic lookups, dictionaries have methods for providing defaults, updating in bulk and building from other data. Dictionary comprehensions let you transform and filter a whole dictionary in one expression.
get and setdefault
PY defaults.py
config = {"host": "localhost"}
print(config.get("port", 8080))
print(config)
port = config.setdefault("port", 8080)
print(port, config)
config.setdefault("port", 9999)
print(config["port"])
Output
8080
{'host': 'localhost'}
8080 {'host': 'localhost', 'port': 8080}
8080get only reads; setdefault reads the value if the key exists, and otherwise inserts the default and returns it. It's handy for grouping:
PY grouping.py
words = ["apple", "avocado", "banana", "blueberry", "cherry"] by_letter = {} for w in words: by_letter.setdefault(w[0], []).append(w) print(by_letter)
Output
{'a': ['apple', 'avocado'], 'b': ['banana', 'blueberry'], 'c': ['cherry']}update
PY update.py
profile = {"name": "Ana", "city": "Lisbon"}
profile.update({"city": "Porto", "job": "engineer"})
profile.update(age=31)
print(profile)
Output
{'name': 'Ana', 'city': 'Porto', 'job': 'engineer', 'age': 31}Removing items
PY remove.py
d = {"a": 1, "b": 2, "c": 3}
print(d.pop("a"))
print(d.popitem())
print(d)
d.clear()
print(d)
Output
1
('c', 3)
{'b': 2}
{}popitem removes and returns the most recently inserted pair — useful for processing a dictionary like a stack.
fromkeys and copy
PY fromkeys.py
fields = ["name", "email", "phone"] blank_form = dict.fromkeys(fields, "") print(blank_form) copy = blank_form.copy() copy["name"] = "Ana" print(blank_form["name"] == "", copy["name"])
Output
{'name': '', 'email': '', 'phone': ''}
True AnaTrap:
dict.fromkeys(keys, []) gives every key the same list object, so appending to one appends to all. Use a comprehension instead: {k: [] for k in keys}.Dictionary comprehensions
PY comprehensions.py
prices = {"tea": 3.0, "cake": 4.5, "juice": 5.0, "water": 1.0}
with_tax = {item: round(p * 1.2, 2) for item, p in prices.items()}
print(with_tax)
expensive = {item: p for item, p in prices.items() if p >= 4}
print(expensive)
inverted = {p: item for item, p in prices.items()}
print(inverted[4.5])
squares = {n: n * n for n in range(1, 6)}
print(squares)
Output
{'tea': 3.6, 'cake': 5.4, 'juice': 6.0, 'water': 1.2}
{'cake': 4.5, 'juice': 5.0}
cake
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}Building dictionaries from two lists
PY zip.py
names = ["Ana", "Ben", "Cleo"] scores = [91, 78, 85] results = dict(zip(names, scores)) print(results) ranked = {name: rank for rank, name in enumerate(sorted(results, key=results.get, reverse=True), 1)} print(ranked)
Output
{'Ana': 91, 'Ben': 78, 'Cleo': 85}
{'Ana': 1, 'Cleo': 2, 'Ben': 3}Sorting a dictionary
Dictionaries keep insertion order, so "sorting" one means building a new one from sorted items:
PY sort.py
population = {"Porto": 232_000, "Lisbon": 545_000, "Braga": 193_000}
by_name = dict(sorted(population.items()))
by_size = dict(sorted(population.items(), key=lambda kv: kv[1], reverse=True))
print(list(by_name))
print(list(by_size))
Output
['Braga', 'Lisbon', 'Porto'] ['Lisbon', 'Porto', 'Braga']
Safely reading nested data
PY nested_get.py
response = {"user": {"profile": {"city": "Oslo"}}}
empty = {"user": {}}
def city_of(data):
return data.get("user", {}).get("profile", {}).get("city", "unknown")
print(city_of(response), city_of(empty), city_of({}))
Output
Oslo unknown unknown
Quick reference
| Method | Does |
|---|---|
get(k, default) | Read with a fallback |
setdefault(k, default) | Read, or insert the default |
update(other), |= | Merge in place |
pop(k, default), popitem(), clear() | Remove |
keys(), values(), items() | Views for looping |
dict.fromkeys(keys, value), copy() | Create |