Why one change is adopted when another is not?

a = [1,2,[9,10,45]] b = a[:] b[1] = 7 b[2][2] = 7 print(a) output : [1,2,[9,10,7]] why did a adopt the second change but not the first one??

4/8/2020 8:57:47 PM

M Tamim

2 Answers

New Answer


When you write b = a[:], it makes a shallow copy of the elements in the list. Which means if the element in the list is immutable it will be copied to the new list as a new element else it's reference will be copied to the new list. This implies any change made to the mutable element will be reflected in both the list. Having said that you need to remember one thing. All numbers between -5 to 256 (inclusive) gets the same id irrespective of whether they are inside mutable or immutable element or are present as standalone elements. This range may be extended on both sides i.e below -5 and greater than 256 but as of now official documentation mentions the above range only. Also some smaller strings too may get the same id throughout the program. In short it is implementation details. Anyways coming back to the question element a[2] is a mutable element(a list). After shallow copy (b=a[:]) the element b[2] has the same reference as a[2], now you make changes to b[2] it gets reflected in a[2] also. You also made changes to b[1] but it was a copy not reference hence changes made to b[1] was not reflected back in list a. Run the program below to better understand it. a = [1,2,[9,10,45]] print(f"a's id = {id(a)}") b = a[:] print(f"b's id = {id(b)}") print(f"a[0] id = {id(a[0])}") print(f"b[0] id = {id(b[0])}") print(f"a[1] id = {id(a[1])}") print(f"b[1] id = {id(b[1])}") print(f"a[2] id = {id(a[2])}") print(f"b[2] id = {id(b[0])}") print(f"b[1] value before = {b[1]}") b[1] = 7 print(f"b[1] value after = {b[1]}") print(f"b[1] id after = {id(b[1])}") print(f"a[2][2] value before = {a[2][2]}") print(f"a[2][2] id before = {id(a[2][2])}") print(f"b[2][2] value before = {b[2][2]}") print(f"b[2][2] id before = {id(b[2][2])}") b[2][2] = 7 print(f"a[2][2] value after = {a[2][2]}") print(f"a[2][2] id after = {id(a[2][2])}") print(f"b[2][2] value after = {b[2][2]}") print(f"b[2][2] id after = {id(b[2][2])}") print(a) print(f"a value after all changes = {a}") print(f"a id after all changes = {id(a)}")


a = [1,2,[9,10,45]] print('a',a) b = a[:] print('b', b) b[1] = 7 print('b', b) b[2][2] = 7 print('b', b) a[1] = 7 print('a', a) #output : [1,2,[9,10,7]] #why did a adopt the second change but not the first one?? #try to run this you will have some idea. # the second changed the value of 'a' because in the second one we are replacing the element of another list which is nested in 'a', while on the otherhand in the first case we are trying to replace the value of 'a' using b i.e. b[1]=7 directly and not 'a' itself.