Concepts / List Mutation and Side Effects

List Mutation and Side Effects

Identity (is) checks whether two variables refer to the same object in memory; equivalence (==) checks whether two objects have the same value.

  • Programming

Why a Backup Can Change

Suppose one variable refers to a list of scores and another variable is intended to be a backup. You change the original list, but the backup changes too. The problem is usually not the list operation itself. The problem is that both variables may refer to the same list object. To understand this side effect, separate two questions: do the objects contain the same data, and are the variables referring to the very same object?

Identity asks whether two variables refer to the same object. Equivalence asks whether the objects have the same value.

Two Ways to Relate Variables

The equality operator == checks value equivalence. It asks whether two objects contain the same data. The identity operator is checks object identity. It asks whether two variables refer to the same object in memory. These tests can produce different results: two separate lists can contain the same elements, so == can be True while is is False.

same valuessame valuesdifferent objectdifferent objecta[1, 2, 3]a == bTrueb[1, 2, 3]a is bFalse
How can two objects contain the same values while still being different objects?

Identity implies equivalence: if two variables refer to one object, that object has the same value as itself. Equivalence does not imply identity: separate objects can contain identical data.

Tracing an Alias Through Mutation

python

The assignment b = a does not create a second list. It creates an alias: both names refer to the same list object. Therefore, changing the list through b also changes what can be seen through a. After the append operation, both a and b refer to the list containing [1, 2, 3, 4]. The side effect occurs because the list is mutable and the two variables share its identity.

refers torefers toalist object[1, 2, 3, 4]b
What changes when two variables refer to the same list and one variable mutates it?

What do you think happens?

After b = a and b.append(4), what does a refer to?

  • The original list [1, 2, 3]
  • The changed list [1, 2, 3, 4]
  • A separate list containing [1, 2, 3, 4]
Reveal answer

Answer: The changed list [1, 2, 3, 4]

Assignment creates an alias here. Both variables refer to the same mutable list, so a also observes the mutation made through b.

Creating a Separate List

python
Output
same_values: True
same_object: False

The two list literals create separate list objects. Their contents are equivalent, so a == b is True. Their identities are different, so a is b is False. If one list is later mutated, the other list remains a separate object rather than automatically sharing that mutation.

guaranteescan still havesame objectsame valueseparate objects
Why does x is y guarantee x == y, while x == y does not guarantee x is y?

Lists and Strings in Memory

TypeCan contents change after creation?Relevant identity behavior
ListYes; lists are mutableCreating two lists with the same elements creates separate list objects
StringNo; strings are immutablePython often reuses the same string object when possible

Strings and lists differ because strings are immutable while lists are mutable. Python can often reuse a string object because its contents cannot be changed after creation. Reusing a mutable list would be unsafe: changing one reference could unexpectedly affect every variable that shared the list. For lists, separate list creation helps avoid that kind of unintended aliasing.

in-place changenew valuelist[1, 2]list[1, 2, 3]stringcatstringcats
What happens when a list is changed in place compared with when a string appears to be changed?

Mistakes with Aliases

  • Assuming that equal values mean the same object

    Separate list objects can have the same value while having different identities.

    Fix: Use == to test their contents and is to test whether they are one shared object.

  • Treating b = a as a copy of a list

    This assignment creates an alias, so both variables refer to the same list.

    Fix: Know whether you want shared data or an independent copy before modifying the list.

  • Using is when you mean equal in value

    is checks identity, not whether two separate objects contain the same data.

    Fix: Use == for value equivalence.

  • Expecting lists and strings to have the same reuse behavior

    Changing a shared mutable list could affect every variable referring to it.

    Fix: Remember that lists are mutable and strings are immutable.

When debugging an unexpected list change, inspect the relationship between the variables before inspecting the mutation itself. Ask whether the variables are aliases or refer to separate list objects. If the data must remain independent, create a separate copy explicitly rather than relying on an assignment that only creates another name for the same object.

Check Your Reasoning

MEDIUM

For each pair, decide whether the variables are equivalent, identical, both, or neither. Then identify which operator would test the relationship you chose. Pair A: a = [4, 5] and b = [4, 5] Pair B: a = [4, 5] and b = a

Hints
  • A list literal creates a list object.
  • Assignment from one variable to another creates an alias.
  • Use == for value equivalence and is for identity.

Comparing the Two Pairs

Classify the relationships in Pair A and Pair B.

Pair A: The two list literals create separate list objects. Their values are equivalent, but their identities are different. Therefore == is True and is is False.

Pair B: The assignment b = a creates an alias. Both variables refer to one list object. Therefore the objects are identical and are also equivalent.

Mutation consequence: A mutation made through either variable in Pair B is visible through the other variable because both names refer to the same mutable list.

Pair A: equivalent but not identical. Pair B: identical and equivalent.

The Identity Test

  1. Identity and equivalence answer different questions. The is operator checks whether two variables refer to the same object, while == checks whether their objects contain the same value. Assigning one variable to another creates an alias, so a mutation to a shared list can be observed through both variables. Creating separate list literals produces separate objects that may still be equivalent. Strings are immutable and can often be reused, while lists are mutable and are handled as separate objects when separately created.

Key Takeaways

  • The is operator tests identity; the == operator tests value equivalence.
  • If two variables refer to the same object, they are automatically equivalent.
  • Two separately created lists can contain the same values without being the same object.
  • Assignment such as b = a creates an alias rather than an independent list.
  • Mutating a shared list creates side effects visible through every variable that refers to it.