Copy Without Hiding Shared Data
Create a new outer collection deliberately while keeping shared nested mutable values visible and stating which object a function changes.
When two names refer to one collection, they are aliases. That is useful when two parts of a program should share changes. When a program needs a separate working collection, plain assignment is not enough. It needs a copy.
Copy a Flat Collection
The .copy() method creates a new outer collection containing the same items:
There are now two list objects:
original ─────> list A: [18, 21]
working ─────> list B: [18, 21, 23]
The copied numbers can safely appear in both lists because numbers do not change in place. Appending to list B changes only its outer list.
Lists, dictionaries, and sets all provide .copy():
Each copy is a new outer collection. Appending to readings_copy, assigning a
new key in by_sensor_copy, or adding to active_copy leaves the corresponding
outer source collection unchanged.
Q1. Predict a flat list copy
What does this program display?
Select one choice, then check.
HintCount the outer lists
.copy() creates list B before append changes it.
SolutionOnly the copied list grows
original still refers to list A, [18, 21]. working refers to list B,
which becomes [18, 21, 23].
A Shallow Copy Can Still Share Nested Lists
The copy made by .copy() is a shallow copy. It creates a new outer
collection, but it does not recursively copy mutable values stored inside that
collection.
Consider a dictionary whose values are lists:
The outer dictionaries are separate, but both "north" entries refer to the
same inner list:
original ─────> dictionary A ── "north" ──┐
├──> list N: [18, 21]
working ─────> dictionary B ── "north" ──┘
Appending through either dictionary changes list N:
An outer change remains independent:
These two results are not contradictory. The dictionaries are separate; the inner north list is shared.
| Operation | Dictionary A | Dictionary B | Shared list N |
|---|---|---|---|
working = original.copy() | unchanged | new outer copy | [18, 21] |
working["north"].append(23) | same outer keys | same outer keys | [18, 21, 23] |
working["west"] = [19] | no "west" key | gains "west" | unchanged |
Q2. Trace a shared nested list
What does original["north"] contain after this code runs?
Select one choice, then check.
HintDraw the inner object separately
.copy() created another dictionary, not another list for each value.
SolutionThe nested append is shared
Both dictionaries contain a reference to the same north list. Appending 23
through working changes that list, so original["north"] is
[18, 21, 23].
Return a Changed Flat Copy
A function can leave the caller's flat list unchanged by copying before it makes corrections:
The indexed assignment changes one position in the copied list. The function returns that changed copy:
This function works with a flat list of numbers. If its input contained nested
lists, the ordinary .copy() would still share those inner lists. The function
contract and the data shape must agree.
Q3. Return a corrected copy
Repair the function so it returns corrected readings without changing the caller's list.
Editable Python
Ready to run.
HintCreate the second outer list first
Replace the plain assignment with readings.copy() before the loop changes
any position.
SolutionCorrect only the copy
.copy() creates a new outer list, dictionary, or set. Flat outer changes are
then independent, but nested mutable values remain shared unless the program
copies them deliberately. Keeping outer and inner objects separate makes both
aliases and shallow copies predictable before debugging begins.