Python Basics - Mutable vs Immutable Objects

Python Basics - Mutable vs Immutable Objects

Introduction - Objects, Values, and Types


All the data in a Python code is represented by objects or by relations between objects. Every object has an identity, a type, and a value.

Mutable and Immutable Data Types in Python


  • Some of the mutable data types in Python are list, dictionary, set and user-defined classes.

  • On the other hand, some of the immutable data types are int, float, decimal, bool, string, tuple, and range.

It’s time for some examples. Let’s start by comparing the tuple (immutable) and list (mutable) data types. From both data types, we can access elements by index and we can iterate over them. The main difference is that a tuple cannot be changed once it’s defined.

Indexing lists and tuples

list_values = [1, 2, 3]
set_values = (10, 20, 30)
print(list_values[0])
1
print(set_values[0])
10

Changing values: lists vs tuples

list_values = [1, 2, 3]
set_values = (10, 20, 30)
list_values[0] = 100
print(list_values)
[100, 2, 3]

set_values[0] = 100
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

We can see that when we try to change the tuple we get an error, but we don’t have that problem with the list.

Tuple vs List Expanding

list_values = [1, 2, 3]
set_values = (1, 2, 3)
print(id(list_values))
140062164740872
print(id(set_values))
140062164083768

list_values += [4, 5, 6]
set_values += (4, 5, 6)
print(id(list_values))
140062164740872
print(id(set_values))
140062163776040

We can see that the list identity is not changed, while the tuple identity is changed. This means that we have expanded our list, but created a completely new tuple.

Other Immutable Data Type Examples

We have seen that some of the other immutable data types are integers and strings. Once they are initialized, their values cannot be changed.

number = 42
print(id(number))
9063936

number += 1
print(id(number))
9063968
text = "Data Science"
print(id(text))
140062163360240

text += " with Python"
print(id(text))
140062164672960

We see that both for the number and text variables, their identity is changed. This means that new variables are created in both cases.

Copying Mutable Objects by Reference

Let’s see what happens if we give two names of the same object for a mutable data types.

values = [4, 5, 6]
values2 = values
print(id(values))
140062164255048
print(id(values2))
140062164255048

values.append(7)
print(values is values2)
True
print(values)
[4, 5, 6, 7]
print(values2)
[4, 5, 6, 7]

We can see that the variable names have the same identity meaning that they are referencing to the same object in computer memory. Reminder: the is operator compares the identity of two objects.

So, when we have changed the values of the second variable, the values of the first one are also changed. This happens only with the mutable objects. You can see how you can prevent this with created new list or using slicing.

numbers = [10, 42, 28, 420]
numbers_copy = numbers
numbers_copy[2] = 100
numbers      
[10, 42, 100, 420]
numbers_copy 
[10, 42, 100, 420]

ratings = [4.5, 5.0, 3.5, 4.75, 4.00]
ratings_copy = ratings[:]
ratings_copy[0] = 2.0
ratings      
[4.5, 5.0, 3.5, 4.75, 4.0]
ratings_copy 
[2.0, 5.0, 3.5, 4.75, 4.0]

characters = ["A", "B", "C"]
characters_copy = list(characters)
characters_copy[-1] = "D"
characters      
['A', 'B', 'C']
characters_copy 
['A', 'B', 'D']

Copying Immutable Objects

Let’s try to do a similar example with an immutable object. We can try to copy two strings and change the value in any of them.

text = "Python"
text2 = text
print(id(text))
140062164731360
print(id(text2))
140062164731360
print(text is text2)
True

text += " is awesome"
print(id(text))
140062163372984
print(id(text2))
140062164731360
print(text is text2)
False

print(text)
Python is awesome
print(text2)
Python

The == operator

Sometimes we don’t want to compare the identity of two objects, but to compare the values of these objects. We can do this using the == operator.

numbers = [1, 2, 3]
numbers2 = [1, 2, 3]
print(numbers == numbers2)
True

print(numbers is numbers2)
False

We can clearly see the two objects have the same values, but their identities are different.

Immutable Object Changing Its Value

As we said before the value of an immutable container that contains a reference to a mutable object can be changed if that mutable object is changed. Let’s see an example of this.

skills = ["Programming", "Machine Learning", "Statistics"]
person = (129392130, skills)

print(type(person))
<class 'tuple'>
print(person)
(129392130, ['Programming', 'Machine Learning', 'Statistics'])

skills[2] = "Maths"
print(person)
(129392130, ['Programming', 'Machine Learning', 'Maths'])

We have changed the value of the skills variable. The other variable person contains a reference to the skills variable and that’s why its value is updated, too.

Summary