Mutable vs Immutable Objects in Python

Introduction

Python is an amazing language. Due to its simplicity, many people choose it as their first programming language. Experienced programmers also use Python all the time, thanks to its wide community, abundance of packages, and clear syntax. But there is one problem that seems to confuse both beginners and some seasoned developers: Python objects. Specifically, the difference between mutable and immutable objects. In this post we will review the knowledge about Python objects, learn the difference between mutable and immutable objects, and see how we can use the interpreter to better understand how Python works.

What is an object?

An object is anything that a variable can point to. In Python, everything (including a class) is an object. (In fact, classes as objects have their own class: a metaclass.) A particularly common object is an int object, or integer. Other objects include strings, dictionaries, and lists.
Objects contain data but behave like functions; they act in the way expected of them based on their type. Objects have attributes which are associated with specific objects and take specific values. Objects also have methods which act as functions using both the object and its arguments.

class Person:
""" defines a new person """

def __init__(name="", age=0)
""" initializes person """
self.name = name
self.age = age
def print_name(self):
""" prints name of the person """
print self.name
>>> jorge = Person("Jorge", 28)

Identification and type functions

What are id() and type() in Python? id () and type () are two built-in functions used to get information about various objects.

# Declaring two string objects:
>>> obj1 = "Hi"
>>> obj2 = "Galia"
# Getting their ids:
>>> id(obj1)
139725014564344
>>> id(obj2)
139725014575280
>>> obj3 = "Galia"
>>> obj4 = "Galia"
>>> id(obj3)
139725014575280
>>> id(obj4)
139725014575280
>>>id(obj3) == id(obj4)
True
>>>id(obj3) is id(obj4)
True
# Example:
>>> a = 50
>>> type(a)
<class: 'int'>
>>> b = "Holberton"
>>> type(b)
<class: 'string'>
>>> type(a) == type(b)
False

Mutable and Immutable Objects

As mentioned earlier, when an object is created it is assigned a unique object ID. Depending on the type of object, a mutable object can be changed after it is created and an immutable object cannot be changed.
Objects of built-in types like (int, float, str, tuple) are immutable while objects of built-in types like (list, set, dict) are mutable. Custom classes are generally mutable, but can be configured to simulate immutability.

Mutable Objects

Mutable objects are those that can be changed after creation. The most common mutable objects in Python are lists. Mutable objects are very easy to change and are often used in cases where you might want to modify a value later on. Let’s make a list:

>>> my_list = [1, 2, 3, 4]
>>> id(my_list)
140659361103048
>>> my_list.append(5)
>>> print(my_list)
[1, 2, 3, 4, 5]
>>> id(my_list)
140659361103048

Immutable Objects

Immutable objects consists of number, string, tuple, frozen set, and bytes. These are objects that can’t be manipulated; for example:

# Declaring a tuple object:
>>> a = (1, 2, 3)
>>> a.append(3)
# Getting an error when I try to append a new number to the tupleTraceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'append'

Why does it matter and how differently does Python treat mutable and immutable objects

From examples above we can see that integers and strings are stored in one location and the variables are pointing to that same location. Since we are looking at it form object oriented perspective we know everything is an object in python so no matter how many variables we have pointing to 6 or “Hello” there is only one instance of it in the memory and all the variables are just pointing to that same object. So they are all aliases in a way. Ok, so that makes sense but what about floats and tuples. They are immutable, so why don’t they have the same addresses. Let’s keep checking and see if we can find an answer.

float                                       tuple
>>> b += 1 >>> d = (1, 2, 3, 4)
>>> id(b) >>> id(d)
140634296045976 139750557198520
>>> b -= 1 >>> id((1, 2, 3, 4))
>>> id(b) 139750517631640
140634296045688 >>> a = (1, )
>>> b -= 1 >>> type(a)
>>> id(b) <class 'tuple'>
140634296045976 >>> a = (1, 2)
>>> b += 5 >>> b = (1, 2)
>>> id(b) >>> a is b
140634296045688 False
>>> b >>> a = ()
10.7 >>> b = ()
>>> id(10.7) >>> a is b
140634296045976 True

How arguments are passed to functions and what does that imply (for mutable and immutable objects)

Now one more thing we need to take into consideration is how are mutable vs. immutable objects are being affected when they are passed to functions.

def increment(n):
n += 1
>>> a = 1
>>> increment(a)
>>> print(a)
1
def increment(n):
n.append(4)
>>> l = [1, 2, 3]
>>> increment(l)
>>> print(l)
[1, 2, 3, 4]
def assign_value(n, v):
n = v
>>> l1 = [1, 2, 3]
>>> l2 = [4, 5, 6]
>>> assign_value(l1, l2)
>>> print(l1)
[1, 2, 3]
>>> a = [1, 2, 3]
>>> b = a[:]

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store