Python Tutorial
Python Dictionary Methods
Dictionaries have methods for access, update, and default values.
setdefault and fromkeys
setdefault inserts only if the key is missing. fromkeys builds a dict from keys.
car = {"brand": "Ford"}
car.setdefault("color", "white")
car.setdefault("brand", "BMW") # ignored
print(car)
print(dict.fromkeys(["a", "b"], 0))📘 Real-World Deep Dive
<code>dict</code> ships with an expressive API: <code>get/setdefault/update/keys/values/items/pop/popitem/clear/copy|merge</code>. Knowing these by heart lets you express "merge-with-defaults" type logic in one line.
Real-Life Scenario
Layered configuration: defaults → environment → user overrides; merge precedence is "later wins".
Real-Life Example
from typing import Any
DEFAULTS: dict[str, Any] = {
"timeout": 30,
"retries": 3,
"endpoints": {"public": "https://api", "private": "https://intl"},
"log_level": "INFO",
}
ENV: dict[str, Any] = {
"timeout": 60,
"endpoints": {"private": "https://intl-eu"},
"region": "eu-west-1",
}
USER: dict[str, Any] = {
"log_level": "DEBUG",
"extra_headers": {"X-Trace": "yes"},
}
def deep_merge(base: dict[str, Any], over: dict[str, Any]) -> dict[str, Any]:
out = dict(base)
for k, v in over.items():
if isinstance(v, dict) and isinstance(out.get(k), dict):
out[k] = deep_merge(out[k], v)
else:
out[k] = v
return out
config = deep_merge(DEFAULTS, deep_merge(ENV, USER))
import json
print(json.dumps(config, indent=2))Expected Output
{
"timeout": 60,
"retries": 3,
"endpoints": {
"public": "https://api",
"private": "https://intl-eu"
},
"log_level": "DEBUG",
"region": "eu-west-1",
"extra_headers": {
"X-Trace": "yes"
}
}Common mistakes
- Modifying
d.keys()directly (e.g. converting to a list and sorting) silently mutates the iteration order — calllist(d)instead. dict.pop(k, default)returns the value if present, the default if not — never raisesKeyError.- Mutating a dict returned by
dict.getin your own code doesn't update the dict — you have a copy.
🚀 Performance & Best Practices
d.items()speeds up "dict to its own type" loops vs. two-passfor k: for v.- Constructing with
dict(a=1, b=2)/ unpacking is faster than manual insertion in micro-benchmarks. dict.fromkeys(seq, value)is a single C-level loop — preferable to walking a sequence manually.
🧪 Try It Yourself
- Make
deep_mergeaccept a list of dicts and apply each in turn. - Add a
deep_freeze(d)that returns afrozendataclass-equivalent usingtypes.MappingProxyType. - Time
dict.update(other)vs. your merge loop for 10 k keys.