Python Tutorial
Python Copy Dictionaries
dict2 = dict1 copies the reference. Use copy() or dict() for a shallow copy.
copy() and dict()
Shallow copies share nested objects. Use copy.deepcopy for nested dicts you must isolate.
thisdict = {"brand": "Ford", "model": "Mustang", "year": 1964}
print(thisdict.copy())
print(dict(thisdict))📘 Real-World Deep Dive
Most "copy" of a dict is shallow, and that bites when nested values are mutated. Knowing the safe patterns (<code>copy.deepcopy</code>, dataclass <code>replace</code>, structured cloning) keeps code safe under mutation.
Real-Life Scenario
Clone a feature-flag snapshot before a destructive operation, then run an experiment on the clone without affecting the live config.
Real-Life Example
import copy
from dataclasses import dataclass, field, replace
from typing import Iterable
@dataclass
class FeatureFlags:
env: str = "prod"
allow_list: list[str] = field(default_factory=list)
rates: dict[str, float] = field(default_factory=dict)
live = FeatureFlags(
env="prod",
allow_list=["v1", "v2"],
rates={"new_signup": 0.05, "search_v2": 0.50},
)
# Shallow copy: share the inner lists/dicts.
shallow = copy.copy(live)
shallow.allow_list.append("rogue") # affects live too!
print("live.allow_list :", live.allow_list)
print("shallow.allow_list :", shallow.allow_list)
# Deep copy: independent, safe.
deep = copy.deepcopy(live)
deep.allow_list.append("experiment")
print("deep.allow_list :", deep.allow_list)
# Best for dataclasses: replace() preserves frozen-ness.
@dataclass(frozen=True)
class FrozenFlags:
env: str
allow_list: tuple[str, ...]
flags = FrozenFlags(env="prod", allow_list=("v1", "v2"))
flags2 = replace(flags, allow_list=flags.allow_list + ("v3",))
print("frozen:", flags2)Expected Output
live.allow_list : ['v1', 'v2', 'rogue']
shallow.allow_list : ['v1', 'v2', 'rogue']
deep.allow_list : ['v1', 'v2', 'experiment']Common mistakes
copy.copyon a dict copies the outer dict but aliases inner objects.dict(other)andother.copy()are both shallow — verify before mutating nested fields.- For very deep structures,
copy.deepcopycan be slow or hit recursion limits — consider reconstruction.
🚀 Performance & Best Practices
- For dataclasses,
dataclasses.replaceis faster thancopy.deepcopy. - For picklable objects,
copyreg.dispatch_tablecan speed up deep copies with custom reducers. - Avoid blanket
copy.deepcopyin tight loops — copy what you really need.
🧪 Try It Yourself
- Replace
deepcopyin the example with a manual rebuild for speed. - Add a test that asserts
copy.copyon a nested config leaves nested state shared. - Implement a
snapshotmixin that stores a deep copy and exposesrestore().