Every programming language has a different way of storing data. C, for example, requires that you explicitly declare a variable; i.e., you need to say what kind of information it is going to store before you use it for the first time. You need to say if it’s an array of characters, or an array of integers; an integer or a float, etc.
Python doesn’t require an explicit declaration of the kind of objects that you are manipulating. Because of this, you need to understand how to find out what kind of object you are dealing with and which objects can be modified and which ones cannot. This quality of is called mutability and it’s a key concept to understand objects in Python.
One of the functions that allows you to find out what kind of object you are dealing with is type(). The other, id(), will allow you to verify the memory address of an object. As you will see, this can come in handy to understand which objects can be mutable and which objects become something different once you perform operations on them.
Immutable objects cannot be modified after their creation. What this means is that when you perform an operation on them, and you will assign them to the same variable name, you are, in fact, creating a new object.
Mutable objects can be modifed after their creation. You can perform operations on them and their identify won’t change. In other words, they will keep the same memory address.
Understanding mutability is really important to understand what happens in a case like the one illustrated in this example:
>>> a = 1
>>> a += 3
An int (integer) is immutable. So what happens when attempt to modify the integer labeled as “a”? You are creating a new object (which results from the addition of 3) and you are labeling with the name “a”. We can verify that this is, in fact, a different object because it has a different address.
Lists are mutable objects. Let’s see what happens in Python when you modify them. Do they preserve their identity (their memory address) or do they become something different?
>>> a = [1, 2, 3]
[1, 2, 3, 4]
As you can see, “a” was modified but it remained the same object, i.e., it preserved its memory address.
It’s important to be extra careful when objects are passed as arguments to functions, for their behavior will be different depending on whether they are mutable or not. Let’s look at another example to illustrate this point:
>>> def add_value(a, b)
>>> a = a + b
>>> return a
>>> a = 3
>>> b = 5
>>> add_value(a, b)
Since an integer labeled as a is immutable, I can pass it to a function and it will keep its identity as you can verify by looking at its memory address.