Mutable and immutable objects
Table of Contents
Is this what you expect?
The result of the code below is probably what you expect.
a = 3 b = a print(a, b) b = b + 9 print(a, b)
3 3 3 12
Here is similar code that uses lists instead, but the result might surprise you.
a = [3, 4, 5] b = a print(a, b) b.append(6) print(a, b)
[3, 4, 5] [3, 4, 5] [3, 4, 5, 6] [3, 4, 5, 6]
Notice that we changed b by appending 6, yet the value of a has
also changed. In order to understand these examples, we need to cover
the concept of "variables" in Python and the concept of mutability.
Variables in Python
The example above shows that a has to be linked in some way to b
beyond just initially sharing values. In other words, assigning a to
b doesn't just simply copy over the values of a. So what is
happening?
Variables can be thought of as names that are attached to a value. A
name itself is not the value. For example, a above is not a list. At
that point in time, it refers to a particular list.
After we assign b = a, now b is another name that attached to the
same list.
The above diagrams should make it clear what is happening in the example
with lists. The value of a changes when b is modified because they
are referring to the same thing.
Mutability
The logic above explains why b changes along with a, but why didn't
the example with integers behave the same way? This has to do with an
important difference between integers and lists: lists are mutable while
integers are not. Being mutable means that the value can be changed
in-place. Let's walk through the integer scenario in diagrams.
After both a is assigned to 3 and then b is assigned to a, it
looks like this:
Once we modify b by adding 9, b now refers to a new value, while
a is still bound to the original value.
Notice that 3 still exists, unmodified. Now, a second value exists,
and the name b is now bound to it, while a still refers to 3. This
is very different than the list that we changed in-place. This is why we
have write b = b + 9 instead of just b + 9. In order to change the
value of b, we need to reassign the name a because we can't change
the underlying value.
Mutability of some common types
| Type | Mutable |
|---|---|
| int | no |
| string | no |
| tuple | no |
| list | yes |
| dict | yes |
More information
Both of these articles provide great explanations (full of pretty diagrams) of assignments and mutability: