In this article, we have explained the concept of Mutable and Immutable in Python and how objects are impacted with this. We have presented code examples to give an idea how it is used.
After finishing this article, you will understand:
- Mutable and Immutable Objects in Python
- How and Why are they used?
Introduction: Everything is an Object
Before we start deep diving into what these fancy terms mean, you need to know this: Everything in python is an object
If you don't know what an object is, don't worry, for now just understand that object can be anything - an integer, a boolean, a list and so on.
Well a simple definition is: Mutable objects can be updated and Immutable objects cannot be updated, trying to update them would lead to an error.
Sounds easy doesn't it? Well there's much more to that, let's dive in!
As I have said earlier, since everything in python in an object, every variable we create in python holds the instance of the object (If this term sounds scary, don't sweat, you will understand these concepts as we progress ahead).
So, as I was saying, every variable holds the instance of an object, since python is a dynamically typed language, the type will be defined at runtime and it never changes. But the value that particular variable holds, can be changed if it's a mutable object.
Mutable and Immutable Objects
Before we start with examples, let's look at a few examples of mutable and immutable objects.
Mutable Objects: Lists, sets and dictionaries.
Immutable Objects: Integers, floats, tuples and strings.
You might be thinking, Wait! Integers and floats are immutable? But i always change a variables value and i see no error?
Well, it has something to do with python's memory management, you see, when you create and initialise an interger variable in python, python creates adequate memory for that integer required. The variable just points to it. When you try to change the value of a variable, what actually happens is, a new integer object is created in memory and the variable points to the new object. The old integer object will be discarded by python if it sees no more use to it. Lets look at an example and understand it more clearly.
We shall be using the id() function in python. For those of you who are not familiar with the function, understand that it just returns the identity (or in simpler terms, address) of an object (Remember: Everything is an object in python).
Take a close look at the id of var1 and notice how it changes after being assigned 20. Here it basically shifts pointing from integer 10 to integer 20. So the value of integer 10 at address 18.....96 cannot be changed since integer is an immutable object.
Now lets move on to linear data structures. So in python, we have lists, sets, strings and tuples. Lets take one example each of mutable objects and immutable objects and compare how they work.
Let us look at an operation where we take a list and a tuple. Lets try to update a value at an index.
Oh wait! updating an element in list gave us no errors but updating a tuple has given us TypeError. This is what we need to keep in mind while working in immutable objects. The same can be observed with strings. Look at the example below.
Let us look deeper into the example of list, let us look at a list and its address, and look at its address after updating it.
Here we can clearly see that the address of the list has not been updated, even after updating an element in the list. But understand, the address of list1 changes after getting updated.
But wait! If i get an error when i update an immutable object like tuple and string, why havent i ever recieved an error when i concatenate two string? Look at the example below
You have updated the string1 but there was no error! Why did this happen? To understand this, we need to dive again into how memory is managed in python. I will explain what happened in the above code step by step:
- A string object "abc" was created and the variable string1 points to its address
- Now, at the concatenation phase, what actually happens is, a copy of "abc" was made at a new memory location, the string "def" was appended to it, and a new string "abcdef" is formed.
- Now, the variable string1 simply points to the new string "abcdef" instead of "abc".
Look closely at how the address of string1 changes after the concatenation. A similar mechanism is followed during the concatenation of tuples as well. It is important to remember, operations like this tend to be more costly, in terms of speed, since for concatenation, we need to make a copy of the object and then append to it.
Now i'm gonna drop an interesting statement:
Immutable objects are not totally immutable
Wait what? What am i talking about? Just calm down a bit, i will explain everything to you in detail. Now lets take a very interesting example to make you understand what i meant.
let a tuple example = (23, [3,4,5])
Look at the code below
How did i just update a tuple? So here's a very important statement that you need to understand: Each index in the tuple is bound to an object (be it int, float, list), these bindings are perfectly immutable, but the object they are bound to, can be mutable or immutable.
Lets say theres a tuple of integers, each index of the tuple is bound to an integer object which is immutable, therefore it is impossible to update the tuple. Consider another case, where the tuple consists of lists, each of which is mutable and can always be updated.
This is a very important concept to understand to truly understand the core of how objects are classified mutable and immutable.
This is all about mutable and immutable objects in this article at OpenGenus and how they are used in Python.