Memory and References in Python
Lists are passed to functions by reference, meaning the function receives access to the original list, not a copy.
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 caller has a list named letters and passes it to a function. Inside the function, the parameter is another name for access to that same list object. The function does not receive a separate copy. This is why an operation inside the function can change what the caller sees after the function returns.
Tracing a Deletion
What do you think happens?
Before the function delete_head is called, letters contains ['a', 'b', 'c']. The function deletes the element at index 0 through its parameter t. What does letters contain afterward?
Reveal answer
['b', 'c']
The parameter t and the variable letters refer to the same list object. Deleting the element at index 0 changes that shared object, so the caller sees ['b', 'c'] after the function returns.
The delete_head example
A list named letters contains ['a', 'b', 'c']. The function delete_head receives that list through parameter t and removes the element at index 0.
- 1Before the call
letters refers to the list containing ['a', 'b', 'c'].
- 2During the call
The parameter t refers to the same list object. The deletion through t removes 'a' from that object.
- 3After the call
letters still refers to the same object, which now contains ['b', 'c'].
The deletion made through the function parameter is visible through the caller's variable.
Reference Access
A value and a reference are different ideas in this explanation. A number is treated as a value: when a number is passed to a function and modified inside the function, the original number outside remains unchanged. A list is an object. When a list is passed to a function, Python passes a reference to that object rather than a copy of the list itself.
The important question is not which name you are using. The important question is whether an operation modifies the shared list object. If it does, the caller can see the change because both names refer to that object.
Mutation and Rebinding
| Operation | What happens to the list object | Effect visible to caller |
|---|---|---|
| Modify through the parameter | The shared list object changes | Yes |
| Reassign the parameter | The parameter refers to a different list | No |
The distinction between changing the shared object and changing which object the parameter refers to.
Reassigning the parameter is different from modifying the list. If the function assigns the parameter to a new list such as [1, 2, 3], that changes what the parameter refers to, but it does not change the original list variable in the caller. Only modifications to the shared list object are visible to the caller.
Unexpected Changes
Unexpected list mutations often become easier to find when you trace every function call that received the list. Any of those functions could have modified the shared object. Follow the list from the caller into each parameter, then identify the operation that changed the object.
Common mistake Assuming the function receives a copy of the list.
What it looks likeA function removes an element through its list parameter, but the caller's list is then missing that element.
Why it failsThe function parameter and the caller's variable are aliases for the same list object.
Do this insteadCheck whether the function modifies the list object itself. Such a modification is visible to the caller.
Common mistake Treating parameter reassignment as if it were list mutation.
What it looks likeThe parameter is assigned to [1, 2, 3], and the caller expects its original list to become [1, 2, 3].
Why it failsReassigning the parameter changes the parameter's reference, not the caller's original list.
Do this insteadSeparate operations that modify the shared object from assignments that make the parameter refer to another list.
Common mistake Debugging only the caller and ignoring functions that received the list.
What it looks likeA list changes after a function call, but the search for the cause stops before inspecting the function.
Why it failsA function that receives the list can modify the original object through its parameter.
Do this insteadTrace each call that passed the list and inspect the operations performed through the corresponding parameter.
Check Your Reasoning
A caller has a list named data. A function named remove_negatives receives data and deletes elements through its parameter numbers. Predict whether data can change after the function returns, then explain why.
Hints
- Ask whether numbers refers to the original list object or to a copy.
- Focus on whether the function deletes elements from the list object.
- Use the distinction between mutation and parameter reassignment.
The expected conclusion is that data can change. The function receives a reference to data's list object, and deleting elements through numbers modifies that actual object. When the function returns, the caller sees the modified list.
Remember the Path
- 1Passing a list to a function gives the function a reference to the original list rather than a copy.
- 2The caller's variable and the function parameter are aliases for the same list object.
- 3Mutating the list inside the function is visible to the caller.
- 4Reassigning the parameter to another list does not change the caller's original list.
- 5To debug an unexpected mutation, trace every function call that received the list and inspect how each function used its parameter.
Key Takeaways
- A list argument gives a function access to the original list object.
- The parameter inside the function and the caller's variable are aliases for that object.
- Changes made to the shared list are visible outside the function.
- Rebinding the parameter is not the same as modifying the shared list.
- Tracing references and mutations through function calls helps explain unexpected list changes.