Concepts / Memory and References in Python

Memory and References in Python

Lists are passed to functions by reference, meaning the function receives access to the original list, not a copy.

  • Programming
Interactive lab

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

  1. name = object binds a name; b = a makes b point at the same object.
  2. Mutating a list (append, +=) changes the one shared object.
  3. a = a + [x] and y = y + 1 create NEW objects and re-point one name.
  4. 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.

Educational simulation

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.

letterscaller name['a', 'b', 'c']one list objecttfunction parameterrefers torefers to
What contains what, and how can the function parameter and the caller's variable point to the same list object in memory?

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?

  • ['a', 'b', 'c']

  • ['b', 'c']

  • []

Reveal answer
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.

Worked example

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.

  1. 1
    Before the call

    letters refers to the list containing ['a', 'b', 'c'].

  2. 2
    During the call

    The parameter t refers to the same list object. The deletion through t removes 'a' from that object.

  3. 3
    After the call

    letters still refers to the same object, which now contains ['b', 'c'].

Result

The deletion made through the function parameter is visible through the caller's variable.

letterscaller variable['a', 'b', 'c']list objectletterscaller variable['b', 'c']list objectrefers torefers to
What changes in the original list after the function removes the first element through its parameter?

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.

Key point

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.

callerlettersparameter tfunction accesslist object['a', 'b', 'c']delete index 0changes the objectpasses referenceaccessesreceives mutation
How does the list reference move from the caller into the function, and where does the function's access lead?

Mutation and Rebinding

OperationWhat happens to the list objectEffect visible to caller
Modify through the parameterThe shared list object changesYes
Reassign the parameterThe parameter refers to a different listNo

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.

tparametertparametershared listobject is modified[1, 2, 3]new listletterscaller sees changelettersoriginal list unchangedmodifieschange visible throughrefers todoes not refer to
What is the difference between changing the shared list object and assigning the parameter to a new list?

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.

callerlettersdelete_headparameter tlist object['a', 'b', 'c']['b', 'c']after deletionpasses list referenceaccesses through tdeletes index 0
Which function call changed the shared list, and how can the sequence of references and mutations be traced?
  • Common mistake

    Assuming the function receives a copy of the list.

    What it looks like

    A function removes an element through its list parameter, but the caller's list is then missing that element.

    Why it fails

    The function parameter and the caller's variable are aliases for the same list object.

    Do this instead

    Check 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 like

    The parameter is assigned to [1, 2, 3], and the caller expects its original list to become [1, 2, 3].

    Why it fails

    Reassigning the parameter changes the parameter's reference, not the caller's original list.

    Do this instead

    Separate 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 like

    A list changes after a function call, but the search for the cause stops before inspecting the function.

    Why it fails

    A function that receives the list can modify the original object through its parameter.

    Do this instead

    Trace each call that passed the list and inspect the operations performed through the corresponding parameter.

Check Your Reasoning

MEDIUM

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.
Key point

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

  1. 1
    Passing a list to a function gives the function a reference to the original list rather than a copy.
  2. 2
    The caller's variable and the function parameter are aliases for the same list object.
  3. 3
    Mutating the list inside the function is visible to the caller.
  4. 4
    Reassigning the parameter to another list does not change the caller's original list.
  5. 5
    To 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.

Related concepts

More concepts starting with M