+ 7
Why is int immutable and list mutable?
I was reading the book "Learning Python" and it says- 1. age = 42 2. age = 43 In the above the code, we are not changing the value of age, we are only changing the place where the name "age" points to. Reason given: "42" is of type int which is immutable. In the second line, we are creating a new object "43" of type int and assigning this to "age". It means that when we change the 'value' of int, it only changes assignment. But in the following code: 1. a = [1, 2, 3, 4] 2. a[0] = 5 Aren't we just changing the assignment of a[0]? Then why do we say that lists are mutable? Is there any other reason for calling them mutable or do they work differently (that is, lists don't point to int objects but do something different to refer to them)?
24 Answers
+ 17
when we say lists are mutable, it means that lists support assignment and we can change their contents.
for example:
a = [1, 2, 3, 4]
a[0] = 5
so "a" will be changed to:
a = [5, 2, 3, 4]
but you can't do this with tuples, string or integers.
some examples:
b = (1, 2, 3, 4)
b[0] = 5
print(b)
the output will be an error:
'tuple' object does not support item assignment
c = 'Hello'
c[2] = 'i'
print(c)
the output will be an error:
'str' object does not support assignment
d = 2345
d[1] = 4
print(d)
the output will be an error:
'int' object does not support assignment
and you say about age = 42 and age = 43:
when you say
age = 42
and then
age = 43
you are changing the assignment of age.
you are not changing the content of 42, you are changing the content of age.
if you say:
age[1] = 3
it causes an error because integers don't support assignment but when you say
age = 43
you are changing the content of age and assigning it to another number.
+ 4
Really good discussion here... If I might add...
The variable "a" is assigned a pointer reference to a memory location for the integer object containing the value 42. It is this object value in this memory address that is immutable.
In fact, any expression that evaluates to 42 will all end up pointing to the same shared memory space.
The same applies to other integer values.
https://code.sololearn.com/cfESf4Z0FVg2/?ref=app
+ 3
One advice: tag python.
Many great pythonistas here only answer questions with python tag.
You can't miss services of them ever!
Now, coming to your question.
Firstly value of int was 42, then you replaced it to 43. It don't means - it changed only 2 to 3 and 4 was as it was. It is 'replaced'.
Now, for list, you are changing the value of only first element. Except it list was as it was - it is changed. It isn't replaced by new list [5,2,3,4]
+ 3
For instance,
a = 42
b= a
Now both a and b are equal.
But if we change a, b isn't changed since ints are immutable.
a=3
print(b) #Output -> 42
This is not the case in lists.
a= [1, 2]
b=a
a[0] = 3
print(b) #Output -> [3, 2]
This is because lists are mutable.
The basic difference arises on how their values are updated. Updating an int is equivalent to assigning a new int value to the variable and hence the variable is made to point at a new memory location.
However, lists can be updated in place. Hence while updating a section of the list, the changes are made in the same memory location and the reference that links the variable and the memory isn't changed. This is why if multiple variables refer to the same list and one of them is updated (not reassigned), the others get updated as well.
Tuples are immutable and hence cannot be updated in place whereas dictionaries can be and hence are mutable.
+ 2
1 is replaced by 5. Like 42,43 example.
But we are thinking in context of list here, and list isn't replaced by new one.
+ 2
Aditya Rana
The data type of members of this list is integer.
In the previous example we are changing the a[0] = 1 to a[0] = 5.
Yes, we are replacing them.
In your code 'a' isn't changed because you don't do anything with 'a'. You just say
b = a
it means
b = [1, 2, 3, 4]
and then called the functions on 'b'.
For your last question:
When you say
b = list(map(lambda x: x + 1, a))
you are assigning 'b' to a new list.
This new list has been made by adding 1 number to each member of the old list but it is different from old list and it is a new object.
You are not changing the content of the old list, you are making a new list.
Just look at your codes again.
You called lambda function within an iterator and then you called list function. so you made a new list and assigned 'b' to it.
I hope this be helpful.
+ 2
Let's see an example
var_1 = 6
var_2 = var_1
var_1 = 9
print("var_1: {}".format(var_1))
print("var_2: {}".format(var_2))
lst_1 = [1,2,3]
lst_2 = lst_1
lst_1.append(4)
print("lst_1: {}".format(lst_1))
print("lst_2: {}".format(lst_2))
Output:
var_1: 9
var_2: 6
lst_1: [1, 2, 3, 4]
lst_2: [1, 2, 3, 4]
Integers are immutable since a change in var_1 was not reflected in var_2 but in case of list, there was a change making them mutable.
This is happening because when you create a list and assign it to a variable (lst_1), you have to think of this variable as POINTING to the list rather than being EQUAL to it. Whenever you assign another variable (lst_2) to the one you already have assigned the list, both variables point to the SAME list object. Any list modifications will affect ALL variables pointing to it.
+ 2
Srividya Sistla Correct... immutable and interning are separate independent concepts.
Interning simply refers to caching of objects in this context.
Immutability refers to the inability to change the value.
My previous comments are from observations. However, I'm pretty certain I'm accurate based on references I've read over the past year.
+ 1
I think so.
+ 1
Roneel thanks for ur advice :)
+ 1
Aditya Rana
You use 'a' in map but you assigned 'b' to this new list, not 'a'.
You just use 'a' as parameter.
If you want to change 'a' too, you should say
b = list(map(lambda x: x + 1, a))
a = b
and the rest of the code.
+ 1
Aditya Rana
In your new example you called your function on 'a'.
Then, when python interpreter goes to print(b), it goes to the top and see b = a , so
b = [2, 3, 4, 5]
'b' will be change if you change 'a', because we have b = a in our program.
but 'a' won't be change if you change 'b', because we do not have
a = b
in our program.
+ 1
David Carroll
Awesome explanation! Thanks for sharing it!
+ 1
While struggling to understand why integers in python are called immutable when something such as that code given below in Ex1 is valid, I came across this thread. I understand that in the example below the value stored in the memory location of '10' isn't changed but a new memory location is allocated for the value "15" and int1 is redirected to this new value, essentially leaving the 10, an instance of int class, unchanged and thus making it immutable.
Ex1:
int1 = 10
int1 = 15
@ David Carroll, thank you for your explanation. One follow up question though. You mentioned mentioned any expression that evaluates to 42 will be pointing to the same shared memory as that pointed by a (referring to the example in the link provided). I tried to test this for other immutable data types. Please check below. For string and boolean this has been true. But in case of tuples why isnt the id of tuple1 and tuple2 the same?
str1 = 'abc'
str2 = 'abc'
print(id(str1))
print(id(str2))
O/P:
4405381552
4405381552
bol1 = True
bol2 = True
print(id(bol1))
print(id(bol2))
O/P:
4402707936
4402707936
tuple1 = (1,2,3,4)
tuple2 = (1,2,3,4)
print(id(tuple1))
print(id(tuple2))
O/P:
4444701520
4444704304
+ 1
Vidya Oh wow... I don't even remember responding to this post or writing that code from Nov 2018. 😉
I believe the common id values shared by the integers in my sample code are because they are less than the value 256.
This is actually the result of an optimization method known as interning. Python will essentially cache integers between -5 and 256. I believe larger literal integers may also be interned. However, larger calculated integers may be ignored.
Interning applies to short strings values as well.
I believe this can be configured differently across Python environments. But I would need to research again.
Interning is limited only to commonly used integer values and short strings to balance the lookup performance and memory usage.
Tuples aren't necessarily common enough values to justify the lookup costs for existing instances, especially in environments running on limited hardware specs.
Hopefully, this clarification makes sense.
+ 1
@ David Carroll
Thank you very much for replying. I knew I was writing to an old post and didn't expect anyone to reply. So thanks again.
I am a python novice and here I was trying to understand what immutability entails. This is what is my understanding so far:
(a) In python integers, strings, booleans and tuples are immutable. This means that the values stored in the locations pointed by the corresponding objects will remain unchanged. I understand there are some exceptions to this like a list within a tuple can be modified. Apart from such exceptions generally speaking immutable values remain unchanged.
(b) Because of immutability, since the values do not change, in case of small integers (-5 to 256) and 'may be' larger literal integers but not calculated integers and short strings, python saves memory by pointing all that with same values to the same location by a method called "interning". And tuples are not common enough to justify the costs of interning and hence same value tuples do not always point to the same location.
So not all immutable data types/objects have interning, in other words immutability does not guarantee interning.
+ 1
@David Carroll,
Thank you for confirming. Appreciate your time!
0
Roneel what happens to "1" that we replaced? How is this assignment operation done behind the scenes in case of lists?
0
So it creates a new int object 5 and makes a[0] point to it?
0
M.A.R. what is the data type of members of list? It is integers, right? Then are we replacing the previous int 1 with 5 or are we creating a new object?
Also, pls explain why isn't 'a ' changed in the following code?
Edit: ID of 'b' changes when we change its contents. Doesn't it mean it has created a new object?
https://code.sololearn.com/ccPzDnKhOR3Q/?ref=app
Marking it as best so that it comes on top.