Concepts / Understanding Mutability in Python

Understanding Mutability in Python

If you then write b = a, it is tempting to think that Python creates a second list for b.

  • 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 variable a refers to a list. If you then write b = a, it is tempting to think that Python creates a second list for b. Instead, both variable names refer to the same list object. This shared reference is called aliasing. Once you understand that there is one shared object rather than two independent lists, unexpected changes become easier to explain.

python
avariable name[10, 20]one shared list objectbvariable namerefers torefers to
What does the relationship look like after b = a?

Checking Object Identity

The is operator tests object identity: whether two variables refer to the same object. After b = a, the expression a is b is True because both names refer to the same list. This differs from ==. The == operator tests whether two objects have equal values. Therefore, two variables can contain objects with equal values without referring to the same object.

Code walkthrough
a = [10, 20]
b = a

same_object = a is b
same_values = a == b
  1. 1
    The assignment b = a creates an alias rather than an independent list.
  2. 2
    Because a and b refer to the same list, a is b evaluates to True.
  3. 3
    The list also has equal values when accessed through either name, so a == b evaluates to True.
  • a refers to a list.
  • b = a makes b another name for that same list.
  • a is b checks whether the references identify one object.
  • a == b checks whether the list values are equal.
Output
same_object is True and same_values is True
a is bsame objectTrueone shared lista == bequal valuesTrueequal list contentstests identitytests values
How can is distinguish shared identity from equal values?

How Mutation Spreads

A list is mutable, which means its contents can be modified after the list is created. When a and b are aliases for the same list, modifying the list through b changes the one shared object. Reading the list through a then shows that modification too. The variable used for the modification does not determine which list changes; the shared object is what changes.

What do you think happens?

After these statements, what will a contain?

a = [10, 20]
b = a
b.append(30)
  • [10, 20]

  • [10, 20, 30]

  • A separate list containing [30]

Reveal answer
Answer:

[10, 20, 30]

The assignment b = a makes b an alias for the same list as a. The modification through b changes that shared list, so the new element is visible through a.

Output
a = [10, 20]
b = a
b.append(30)

print(a)
print(b)

Output:
[10, 20, 30]
[10, 20, 30]
a[10, 20][10, 20]one shared lista[10, 20, 30][10, 20, 30]the same shared listb[10, 20]b[10, 20, 30]refers torefers toreadsmodified through b
What changes when the shared list is modified through b?

Copying Instead of Aliasing

Use an explicit copying operation when two lists must be independent. The source identifies a[:] and list(a) as ways to create an independent copy. After copying, the two lists are separate objects. A modification to one list does not affect the other.

Worked example

Alias or Independent Copy

Compare b = a with b = a.copy() when a begins as [10, 20].

  1. 1
    Create an alias

    With b = a, both names refer to the same list object. A modification through b is visible through a.

  2. 2
    Create a copy

    With b = a.copy(), b refers to an independent copy of the list. A modification to b does not affect a.

  3. 3
    Choose deliberately

    Use the alias when shared changes are intended. Use an explicit copy when the lists must remain independent.

Result

b = a shares one list with a. b = a.copy() creates a separate list with the same starting values.

python
Output
Output:
[10, 20]
[10, 20, 30]
aalias case[10, 20]one shared objectacopy case[10, 20]a's listbb = abb = a.copy()[10, 20]independent listrefers torefers torefers torefers to
How do b = a and b = a.copy() differ in references and later contents?

Tracing an Unexpected Change

Aliasing often appears as a debugging mystery: a list changes, but the code that reads the list does not seem to modify it. The missing connection may be another variable that refers to the same object. Start by identifying the variables that might share the list, then use is to test their identity. If the test is True, a modification through either variable can explain the unexpected change.

Debugging
items = ["pen", "book"]
backup = items
backup.append("lamp")

print(items)

Output
Output:
["pen", "book", "lamp"]
items["pen", "book"]["pen", "book"]one shared listappend("lamp")modification through backup["pen", "book","lamp"]observed through itemsbackupbackup = itemsrefers torefers toperformschanges shared contents
How can a reference check trace an unexpected change back to another variable?
  • Common mistake

    Assuming b = a creates an independent list

    What it looks like
    a = [10, 20]
    b = a
    b.append(30)
    Why it fails

    The assignment creates an alias. Both names refer to one shared list, so the modification is visible through a.

    Do this instead

    Use b = a[:] or b = list(a) when b must refer to an independent copy.

  • Common mistake

    Using == when the question is whether two variables share one object

    What it looks like
    a == b
    Why it fails

    Equality tests values, not object identity.

    Do this instead

    Use a is b to test whether the two variables refer to the same object.

  • Common mistake

    Treating an unexpected change as if it happened without a cause

    What it looks like

    items changes after another variable is modified

    Why it fails

    Another variable may be an alias for the same mutable list.

    Do this instead

    Check likely aliases with is and decide whether an explicit list copy is needed.

Choosing the Reference Intentionally

StatementRelationshipEffect of modifying b
b = aa and b refer to the same listThe change is visible through a
b = a[:]b refers to an independent copyThe change does not affect a
b = list(a)b refers to an independent copyThe change does not affect a

The assignment form determines whether the two variable names share one list or refer to separate lists.

Practice the Reference Trace

EASY

Consider this sequence:

values = [1, 2]
other = values
other.append(3)

Predict the result of values is other, then predict the contents of values. Finally, explain what assignment could create an independent list instead.

Hints
  • Ask whether other = values creates an alias or a copy.
  • Use is for the identity question.
  • An independent list can be made with a slice or the list constructor.
  1. 1
    Aliasing means that multiple variable names refer to the same object.
  2. 2
    The assignment b = a creates an alias rather than a copy.
  3. 3
    Use is to test whether two variables refer to the same object; use == to test equality of values.
  4. 4
    Because lists are mutable, a modification through one alias is visible through every other alias.
  5. 5
    Use a[:], list(a), or another explicit copying operation when the lists must be independent.

Key Takeaways

  • Aliasing occurs when two or more variables refer to one shared object.
  • Writing b = a makes b an alias for a's object; it does not create an independent list.
  • The is operator checks identity, while == checks equality of values.
  • Mutating a shared list through one variable changes what every alias sees.
  • Use a[:], list(a), or an equivalent explicit copy when independent list contents are required.

Related concepts

More concepts starting with U