Python Forum

Full Version: An interesting BUG with double assignment
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I came across the following bug
D = dict()
D = D['spam'] = dict()
I expected that D['spam'] = dict() would create a new dictionary as a value in D, then the D = part would reassign the variable D as this new empty dictionary.

But this is not what happened! Here is a more detailed version
>>> 
>>> D = dict()
>>> X = D
>>> D = D['spam'] = dict()
>>> D
{'spam': {...}}    # Hey! dictionary D is not empty. It has a key 'spam'
>>> D is D['spam']     # What? D['spam'] is D itself! D is a cyclic object that contains itself
True
>>> X is D
False
>>> X
{}     # X is still the empty dictionary that we created at the beginning
Explanation
The dis module explains what's going on
>>> import dis
>>> dis.dis('D = D["spam"] = dict()')
  1           0 LOAD_NAME                0 (dict)
              2 CALL_FUNCTION            0            # The dict() function is called and its result is on top of the stack
              4 DUP_TOP                                       # The top of the stack is duplicated!
              6 STORE_NAME               1 (D)        # the top element is consumed and assigned to D: from left to right
              8 LOAD_NAME                1 (D)
             10 LOAD_CONST               0 ('spam')
             12 STORE_SUBSCR                         # the duplicated top element is consumed and assigned to D['spam']
             14 LOAD_CONST               1 (None)
             16 RETURN_VALUE
>>> 
Conclusion: when we write
a = b = c = d = value
it is equivalent, in this order to
a = value
b = value
c = value
d = value
When b is a['spam'] it is the new a that is used for the second assignment!

What should I have done?
D['spam'] = D = dict()
Proof
>>> D = dict()
>>> X = D
>>> D['spam'] = D = dict()
>>> D
{}
>>> X
{'spam': {}}
>>> X['spam'] is D
True
D['spam'] = D = dict()
The last assignment wins. The last assignment is an empty dict.

EDIT: End it seems that dict() is assigned to D and not to D["spam"]
(Oct-08-2023, 01:03 PM)DeaD_EyE Wrote: [ -> ]EDIT: End it seems that dict() is assigned to D and not to D["spam"]
Yes it is. The assignment does the same as
value = dict()
D['spam']=value
D = value