Skip to content

← Under the Hood: Objects, Memory, Speed step 14 of 35

Medium Primitives

Selective deep copy: one memo, and the sharing you meant to keep

Copy a config so that some sections are private to the clone and the rest stay deliberately shared — and do it without hanging on a self-referential structure or leaking a pickling error to the caller.

def clone_config(cfg: Config, *, deep_keys: frozenset[str]) -> Config: ...

Config is a slotted dataclass with one field, sections: dict[str, list[object]]. clone_config returns a new Config with a new sections dict, in which:

  • a key in deep_keys maps to a deep copy of its list;
  • every other key maps to the same list object as the original — the sharing is the point, not an oversight;
  • all the deep copies share one memo dict, so cross-references between deep-copied sections survive and a self-referential section terminates;
  • a section that cannot be deep-copied raises ValueError(f"section {key!r} is not deep-copyable: {err}") chained from the original TypeError. copy refuses modules, so a section containing math is the test for this.

The starter does the reflex thing — copy.deepcopy(cfg) — which is correct in the sense that nothing aliases, roughly 3,300x slower than a shallow copy on a 1,000-element structure, and destroys the sharing you asked for.

solve builds a scenario and reports what is shared with what:

def solve(
    sections: dict[str, list[int]],
    deep_keys: list[str],
    appends: dict[str, int],
    cyclic_key: str,
    module_key: str,
) -> dict[str, object]: ...

It constructs the Config, optionally appends the section’s own list to itself (cyclic_key), optionally appends the math module to a section (module_key), clones with deep_keys, then appends each value in appends to the clone’s section of that name. It returns:

key meaning
"error" "", or the message up to the first : if cloning raised
"original" the original sections, ints only
"clone" the clone’s sections, ints only
"shared" sorted keys where clone and original hold the same list object
"cycle_local" whether the clone’s cyclic section refers to itself rather than to the original

Read the assertions carefully: appending to a shallow section is expected to show up in "original" too. That is not a bug in the test, it is the intentional sharing being pinned down. If you cannot state which of your structure’s fields are in which category, clone is not a function you should be writing yet.

Your submission must pass mypy --strict.

Loading visualization…