Why has the value in dict changed in python?

I recently did 2 experiments:

(1):

>>> a = dict(zip([1,2,3],[4]*3)) >>> a {1: 4, 2: 4, 3: 4} >>> a[1] = 111 >>> a {1: 111, 2: 4, 3: 4} 

(2):

 >>> a = dict(zip([1,2,3],[{'a':True,'b':True}]*3)) >>> a {1: {'a': True, 'b': True}, 2: {'a': True, 'b': True}, 3: {'a': True, 'b': True}} >>> a[1]['a']=False # Here I changed the value of a[1]['a'] from True to False >>> a {1: {'a': False, 'b': True}, 2: {'a': False, 'b': True}, 3: {'a': False, 'b': True}} #all 'a' value changed to False. 

Why did this problem arise in (2)? And why is (1) not a problem?

+5
source share
2 answers

Short answer : because dict objects are mutable and int objects are immutable.

Details:

See [{'a': True, 'b': True}] * 3

WITH

 >>> l = [{}] * 3 

you create a list containing 3 links to the same object.

 >>> id(l[0]) 139685186829320 >>> id(l[1]) 139685186829320 >>> id(l[2]) 139685186829320 

Therefore, when you change one of them, you change them all ( in the case of mutable objects ).

If you need a list of different dictionaries, you can do this with

 >>> l = [{} for x in range(3)] >>> id(l[0]) 139685161766216 >>> id(l[1]) 139685161766536 >>> id(l[2]) 139685161766600 

In your case, it should look like this:

 a = dict(zip([1, 2, 3], [{'a': True, 'b': True} for i in range(3)])) 

With immutable objects, it is different .

You cannot change an immutable object. Wherever it seems that you are changing an immutable object, a new object is created instead.

Therefore, when you try to change an immutable object inside a list, a new object is created:

 >>> l = [1] * 3 >>> id(l[0]) 139685185487008 >>> id(l[1]) 139685185487008 >>> id(l[2]) 139685185487008 >>> l[0] = 2 >>> id(l[0]) 139685185487040 # new object created instead of old object being modified >>> id(l[1]) 139685185487008 >>> id(l[2]) 139685185487008 
+7
source

If you use a rethinking of the list (replacement for zip) or a for () loop, you will not use the same object 3 times

 a = {ctr:{'a':True,'b':True} for ctr in range(1, 4)} print a a[1]['a']=False print a 
0
source

Source: https://habr.com/ru/post/1235264/


All Articles