Python3: Mutable, Immutable… everything is object!
How Everything in Python is an Object? Since Python is an object-oriented programming language, you might think that, obviously, everything in Python is an object, every integer, string, list, and functions. But before discussing how everything in Python is an object, let’s see what is an object? In fact, an object is an entity that contains data with associated metadata or functionalities. These data contained in an object are known as the object’s data attributes. Variables are only references to those objects, but because everything in Python is built around this, let’s dig deeper…
Functions id and type
To recognize an object, each one of them has a proper id and type. Multiple objects can however share the same id.
The id function:
There is a builtin function called id(). It helps us obtain the identifier of an object and it’s value may change between each program launch because it’s only the address of the object in the memory at the t time.
The type function:
There’s also a builtin function called type(). It allows us to obtain the type of the object we are passing through. Using the last example, we can suggest that a has integer type. Let’s verify.
There is a lot of existing class types (such as integers, floats, strings, lists, dictionaries, etc…) but a user can also create his own classes.
Python3 has two types of objects: Mutable and Immutable. Here’s a chart of the mutable ones.
Mutable means that the object itself can be modified after creation. As you can see in the chart, lists are mutable objects, so let’s see an example with them.
As in the example, you can see that the id of our created object
lst isn’t changing, this is the value itself. We can also add a value, it will not change again.
Conversely, here are the immutable objects.
By definition, an immutable object cannot be modified itself. Taking integers for example, when we add a value to another one, a new object will be created instead of using the same last one. As you can see below, a has two different ids according to his value.
This is because the operation is possible. As an immutable object cannot be modified, trying to modify some of them will simply throw you an error, like for example in the strings. We cannot edit them like in the C way of doing it.
Why does it matter and how differently does Python treat mutable and immutable objects?
You are probably wondering then, in which case to use mutable or immutable objects. It’s all about a question of use first, but also a matter of rapidity and efficiency.
First, if we continue with our example of strings, if we have to declare two times a long string, habitually, it would take two times the space in memory. But with immutability in python, we can ensure that the data at the pointed memory will not be changed. As so, Python can handles many times the same string without needing to assign the same amount of times the memory. We’ve seen that previously. The same process applies for objects such as floats, Booleans, etc.…
There is however a little exception inside tuples and frozensets. As they might contain different objects types, we can modify their inside values. So even if those two objects are immutable, you will not be able to have the same id of two same objects.
In each case, if you have a doubt, you can always check if two variables are linked to the same object using the “is” keyword. Contrary to “==”, it will not compare the values but the ids of the objects. In the case of a immutable object, it they are declared identically, the result of the comparison between them will be True if this is the same object, False either.
With this behaviour, we can assume that we will need to think twice before using one or other object. We can, for example, use lists as strings If we planned to modify a string of characters. It will avoid errors trying to modify the string object.
How arguments are passed to functions and what does that imply for mutable and immutable objects?
When an argument (which is an object) is passed to a function, a new reference to this object is created. This is the same behaviour for mutable or immutable objects.
In the above example, we can see that either outside or inside the function, while values are not modified, references to objects are not modified.
But this also means that if the values are modified inside the function (which is also an object), the reference will be broken and new objects will be linked to the variables at a local scope, but not for the entire program.
avariable, pointing to the 1 object is passed into the function, the
cobject is pointing to the same 1 object as
aa but after assignment, the
cobject is no more pointing to the 1 object, but the 2 object. We did not have touched the
aobject, so when we exit the function, the
aobject still have the same id
This is valid for an immutable object, but for a mutable one, the behaviour will be the same as previously seen.
The id is not changed while the value of the object itself has changed, even in our program scope, not just inside our function scope
More to know about the python memory handling
There is a functionality in python which acts like a garbage collector.
Taking for example an exercise we had at school, how many objects will be created in this program with two ‘del’? Well in fact, we would have said 2 according to the last things we’ve seen. But python is handling an awesome thing which is the “Garbage Collector”.
Let’s do it step by step:
- A new immutable string object “HBTN” is created. a is a reference to it.
- Another string object “HBTN” is wanted, but as it already exists, b is simply a reference to the same object created earlier.
- A first deletion is performed, but on the a reference. As b is still pointing to the “HBTN” object, the object is not deleted.
- A second deletion is performed, no more variables are references to the “HBTN” object, so it’s placed in the garbage collector until the end of our program execution.
- Hey ! We need a new “HBTN” object, can you please check if you have any in your garbage before creating a new one? That’s what python is asked to do when c is initialized. Because Python is well organized, he finds this garbage called “HBTN” object, and hopefully, the id is still the same! Python is happy, once again, he managed his memory with a lot of efficiency!