Andres Pulido
6 min readSep 30, 2020

--

Python: Mutable, Immutable… everything is an object!

In Python, everything is an object, and everyone who wants to learn Python should understand from the beginning that objects in this programming language can be either mutable or immutable.

Since in Python an object or class can be assigned to a variable or passed as an argument to a function, they are divided between objects that can be changed (mutable) and objects that can’t be changed (immutable).
Almost everything has attributes and methods
For example, an integer in Python is an object, a large block of memory is assigned to be used by the interpreter

Objects and Values:

An object in Python is something you can refer to. Let’s assign some values to a variable. Which essentially means we make var_1 refer to object “Python”

>>> var_1 = "Python"
>>> id(var_1)
2020201920182017

if we do add the same value to another variable we will get the same id as shown below:

>>> var_1 = "Python"
>>> id(var_1)
2020201920182017
>>> var_2 = "Python"
>>> id(var_2)
2020201920182017

Given this, both var_1 and var_2 have same id type. That means they both refer to the same values (objects) and no other space was allocated for the new string with identical values. This is safe to do in Python, since strings are immutable, so it is the way to optimize resources by referring two strings that refer to the same string to the same object (“Python”).

Let’s now check if both variables have the same value and if both refer to the same object in the python interpreter:

>>> var_1 == var_2
True
---------------------
>>> var_1 is var_2
True

ID and Type:

The built-in function id() returns the identity of an object as an integer. This integer usually corresponds to the object’s location in memory, although this is specific to the Python implementation and the platform being used. The is operator compares the identity of two objects.

It is possible to know if an object is mutable with type()function since the mutable objects do not alter their identity number, on the other hand, the immutable objects, yes. Because when you want to change an object of this type you usually create a new one with the change or simply an error message of access to an immutable object.

Let’s have a look to the following example of comparing id’s of an object in Python:

-------------------------------------------------------------------
>>> x = "Python"
>>> y = "Pyhton"
>>> id(x)
140135852055856
>>> id(y)
140135852055856
>>> print(x is y) '''comparing the types'''
True
--------------------------------------------------------------------
>>> a = 50
>>> type(a)
<class: ‘int’>
>>> b = "Pyhton"
>>> type(b)
<class: 'string'>

We have now seen how to compare two simple string variables to find out the types and id’s.

So using these two functions, we can check to see how different types of objects are associated with variables and how objects can be changed.

Mutable and Inmutable Objects:

So as we discussed earlier, a mutable object can change its state or contents and immutable objects cannot.

Mutable objects:

list, dict, set, byte array

Immutable objects:

int, float, complex, string, tuple, frozen set [note: an immutable version of set], bytes

A practical example to find out the mutability of object types

x = 10x = y

We are creating an object of type int. identifiers x and y points to the same object.

id(x) == id(y)id(y) == id(10)

if we do a simple operation.

x = x + 1

Now

id(x) != id(y)id(x) != id(10)

The object in which x was tagged is changed. object 10 was never modified. Immutable objects dont’t allow modification after creation

In the case of mutable objects

m = list([1, 2, 3])n = m

We are creating an object of type list. identifiers m and m tagged to the same list object, which is a collection of 3 immutable int objects.

id(m) == id(n)

Now poping an item from list object does change the object,

m.pop()

object id will not be changed

id(m) == id(n)

m and n will be pointing to the same list object after the modification. The list object will now contain [1, 2].

So what have we seen so far from the above examples?

  • Python handles mutable and immutable objects differently.
  • Immutable is quicker to access than mutable objects.
  • Mutable objects are great to use when you need to change the size of the object, example list, dict etc.. Immutables are used when you need to ensure that the object you made will always stay the same.
  • Immutable objects are fundamentally expensive to “change”, because doing so involves creating a copy. Changing mutable objects is cheap.

Exceptions in immutability:

Not all of the immutable objects are actually immutable. Confused? Let me explain.

As discussed earlier, Python containers liked tuples are immutable. That means the value of a tuple can't be changed after it is created. But the "value" of a tuple is, in fact, a sequence of names with unchangeable bindings to objects. The key thing to note is that the bindings are unchangeable, not the objects they are bound to.

Let us consider a tuple p = (‘Python’, [1, 2, 3])

The above tuple t contains elements of different data types, the first one is an immutable string and the second one is a mutable list. The tuple itself isn’t mutable. i.e. it doesn’t have any methods for changing its contents. Likewise, the string is immutable because strings don’t have any mutating methods. But the list object does have mutating methods, so it can be changed. This is a subtle point, but nonetheless important: the “value” of an immutable object can’t change, but it’s constituent objects can.

Objects in Python

How Objects are Passed to Functions

It’s important for us to know the difference between mutable and immutable types and how they are treated when passed onto functions.

Memory efficiency is highly affected when the proper objects are used.

For example, if a mutable object is called by reference in a function, it can change the original variable itself. Hence to avoid this, the original variable needs to be copied to another variable. Immutable objects can be called by reference because its value cannot be changed anyways.

def updateList(list1):
list1 += [10]
n = [5, 6]
print(id(n)) # 140312184155336
updateList(n)
print(n) # [5, 6, 10]
print(id(n)) # 140312184155336

As we can see from the above example, we have called the list via call by reference, so the changes are made to the original list itself.

Let’s take a look at another example:

def updateNumber(n):
print(id(n))
n += 10
b = 5
print(id(b)) # 10055680
updateNumber(b) # 10055680
print(b) # 5

In the above example, the same object is passed to the function, but the value of the variable doesn’t change even though the object is identical. This is called pass by value. So what is exactly happening here? When the value is called by the function, only the value of the variable is passed, not the object itself. So the variable referencing the object is not changed, but the object itself is being changed but within the function scope only. Hence the change is not reflected.

--

--