Function Parameters and Mutable Objects
The assignment b = a creates an alias, not an independent copy. After that assignment, a and b refer to the same object.
Try it: Names and Objects
How Python variables are names bound to objects: assignment never copies, mutating a list is seen through every name that points at it, and ints are replaced rather than changed.
How it works
- name = object binds a name; b = a makes b point at the same object.
- Mutating a list (append, +=) changes the one shared object.
- a = a + [x] and y = y + 1 create NEW objects and re-point one name.
- Passing a list to a function passes the reference, so the function can change it.
Default run (7 steps): Two names, one list. Every name is a label that points at an object. … Printed: [1, 2, 3] / True
Simplified: Six fixed scripts on a tiny heap; you choose the values. Object numbers are illustrative, not real id() values.
Loading the simulation…
One List, Two Names
Suppose a program uses two variables, a and b, for what appears to be the same list. If changing the list through b also changes what you see through a, the program may not contain two lists at all. It may contain one list with two variable names referring to it. This relationship is called aliasing.
The assignment b = a creates an alias, not an independent copy. After that assignment, a and b refer to the same object.
Checking Identity
Python provides the is operator for testing object identity. The expression a is b is True when both variables refer to the same object and False when they refer to different objects. This is different from ==. The == operator tests whether two objects have equal values. Two variables can therefore contain equal-looking lists while still referring to different list objects.
True
TrueBoth tests are True in this example, but they answer different questions. The equality test says that the values match. The identity test says that a and b refer to the same list object. The identity result is the important clue when investigating aliasing.
Mutation Through an Alias
What do you think happens?
After b = a and b.append(4), what will a contain?
Reveal answer
[1, 2, 3, 4]
The assignment b = a gives both names access to one list. Because the list is mutable, modifying it through b changes the one shared object, which is also visible through a.
a = [1, 2, 3]
b = a
b.append(4)
print(a)
print(b)- 1The first line creates one list and makes a refer to it.
- 2The second line creates an alias: b refers to that same list rather than receiving a new list.
- 3The third line modifies the shared list through b.
- 4The two print calls show the same modification because a and b refer to the same object.
- a refers to a list containing 1, 2, and 3.
- b is assigned the same object referred to by a.
- The list is modified through b.
- Both names now show the modified list.
[1, 2, 3, 4]
[1, 2, 3, 4]Parameters and Shared Lists
A function parameter can refer to the same mutable list that the caller supplies. If the function modifies that list through its parameter, the caller can observe the modification through its original variable. The parameter is another name referring to the object passed into the function; it does not automatically make an independent list copy.
["old", "new"]When debugging a function that unexpectedly changes a caller's list, inspect whether the function parameter and the caller's variable refer to the same object. The is operator helps verify that relationship.
Aliases and Independent Copies
If a program needs two lists whose later modifications are independent, create a copy explicitly. The source identifies a[:] and list(a) as ways to create an independent copy of a list. In contrast, b = a preserves the shared relationship.
| Operation | Relationship | Effect of modifying b |
|---|---|---|
| b = a | b and a refer to the same list | The modification is visible through a |
| b = a[:] | b refers to an independent list copy | The modification does not affect a |
| b = list(a) | b refers to an independent list copy | The modification does not affect a |
The assignment form determines whether two list variables share one object or refer to separate list objects.
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 5]Tracing an Unexpected Change
Aliasing bugs often appear as an unexpected list change: one part of a program modifies a list, and another variable appears to change without being assigned. Trace the variables that refer to the list, then test likely pairs with is. If the test is True, a modification through either name affects the same mutable object.
Common mistake Assuming b = a creates a second list.
What it looks likea = [1, 2] b = aWhy it failsThe assignment makes b refer to the same list object as a.
Do this insteadUse b = a[:] or b = list(a) when an independent list is required.
Common mistake Using == when the debugging question is whether two variables share one object.
What it looks likea == bWhy it failsEquality compares values, not object identity.
Do this insteadUse a is b to test whether the variables refer to the same object.
Common mistake Forgetting that a function parameter can refer to the caller's mutable list.
What it looks likeA function modifies its list parameter, and the caller's list changes.
Why it failsThe parameter can refer to the same list supplied by the caller.
Do this insteadCheck the identity relationship and create a list copy when the function should work independently.
When a list must not be changed through another variable or function parameter, make the independence explicit with a[:] or list(a). When a change is unexpected, test whether the two variables are aliases before searching for a more complicated cause.
Practice the Trace
A program contains a list named scores. Another variable receives scores with the assignment backup = scores. Before any modification, decide what scores is backup will return. Then decide what scores will contain after backup is modified. Finally, describe one change that would make backup independent from scores.
Hints
- Ask whether the assignment creates an alias or a copy.
- Use the difference between is and == to identify the relevant test.
- An independent list can be created with a slice or the list constructor.
Tracing the Shared Object
Let scores = [10, 20], backup = scores, and then modify backup by adding 30. What identity relationship exists, and what values are visible through both variables?
- 1Identify the assignment
The assignment backup = scores creates an alias rather than an independent copy.
- 2Test identity
scores is backup is True because both variables refer to the same list object.
- 3Apply the mutation
Adding 30 through backup modifies the shared list.
- 4Inspect both names
Both scores and backup show [10, 20, 30] because each name refers to the modified object.
The variables are aliases. To prevent the shared change, create backup with scores[:] or list(scores).
Key Takeaways
- 1Aliasing means that multiple variables refer to the same object.
- 2The assignment b = a creates an alias, not a copy.
- 3Use is to test identity and == to test equality of values.
- 4A mutation to a shared list is visible through every variable that refers to that list, including a function parameter.
- 5Use a[:] or
list(a)to create an independent list copy when later modifications must remain separate.
At a glance
- Aliasing occurs when two or more variables refer to one mutable object.
- The is operator reveals whether two variables refer to the same object.
- Mutating a shared list through one variable changes what other aliases observe.
- Function parameters can refer to the caller's list and mutate that shared object.
- Use a[:] or
list(a)to create an independent list instead of an alias.