Prefer immutable values
A function that changes the list or dict it was given surprises its caller, who may still be using it. Code that changes shared objects can only be understood by following it in time order.
Prefer to return new values:
sorted(items)instead ofitems.sort(){**prices, "tea": 3}instead ofprices["tea"] = 3- tuples and frozensets for collections that should not change
- frozen dataclasses with
dataclasses.replacefor records
from dataclasses import dataclass, replace
@dataclass(frozen=True)
class Settings:
theme: str = "light"
size: int = 14
base = Settings()
big = replace(base, size=18)
print(base)
print(big)replace builds a copy with some fields changed. base is untouched, so anything holding it still sees what it saw before.
Changing an object your function created itself is fine. The rule is about values that other code can see.
Your task
Make add_item(cart, name, qty=1) return a new dict and normalized(names) return a new sorted list of stripped, lower-case names, both leaving their arguments untouched. Turn Config into a frozen dataclass with host and port, and add with_port(port) returning a changed copy.
The explanation opens here once every check passes.