+ 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)?

11th Nov 2018, 6:06 PM
Aditya Rana
24 Réponses
+ 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.
12th Nov 2018, 5:34 AM
M.A.R.
M.A.R. - avatar
+ 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
15th Nov 2018, 6:59 AM
David Carroll
David Carroll - avatar
+ 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]
11th Nov 2018, 6:59 PM
Roneel
Roneel - avatar
+ 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.
12th Nov 2018, 10:34 AM
Mayur Garg
Mayur Garg - avatar
+ 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.
11th Nov 2018, 7:06 PM
Roneel
Roneel - avatar
+ 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.
13th Nov 2018, 6:27 PM
M.A.R.
M.A.R. - avatar
+ 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.
16th Nov 2018, 2:58 AM
Tamoghna Saha
+ 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.
8th Feb 2020, 10:11 PM
David Carroll
David Carroll - avatar
+ 1
I think so.
11th Nov 2018, 7:12 PM
Roneel
Roneel - avatar
+ 1
Roneel thanks for ur advice :)
13th Nov 2018, 12:35 PM
Aditya Rana
+ 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.
13th Nov 2018, 6:37 PM
M.A.R.
M.A.R. - avatar
+ 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.
13th Nov 2018, 7:09 PM
M.A.R.
M.A.R. - avatar
+ 1
David Carroll Awesome explanation! Thanks for sharing it!
15th Nov 2018, 1:44 PM
Aditya Rana
+ 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
6th Feb 2020, 1:22 AM
Srividya Sistla
+ 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.
7th Feb 2020, 4:56 AM
David Carroll
David Carroll - avatar
+ 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.
8th Feb 2020, 3:56 AM
Srividya Sistla
+ 1
@David Carroll, Thank you for confirming. Appreciate your time!
9th Feb 2020, 8:00 PM
Srividya Sistla
0
Roneel what happens to "1" that we replaced? How is this assignment operation done behind the scenes in case of lists?
11th Nov 2018, 7:05 PM
Aditya Rana
0
So it creates a new int object 5 and makes a[0] point to it?
11th Nov 2018, 7:08 PM
Aditya Rana
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.
13th Nov 2018, 4:43 PM
Aditya Rana