0

For the life of me I cannot explain why this is happening:

class Foo():

    def __init__(self):
        self.x = 'x'

class Bar():

    def __init__(self):
        self.items = {}

bar = Bar()
bar.items['a'] = Foo()

foo_dict = bar.items['a'].__dict__
bar_dict = bar.__dict__

print(bar.items) # {'a': <__main__.Foo object at 0x7ff68f217690>}
bar_dict['items']['a'] = foo_dict
print(bar.items) # {'a': {'x': 'x'}}

Why does bar_dict['items']['a'] = foo_dict change the original Foo() instance?

Edit: thanks for all the replies guys. I understand it better now. It can be shown more succinctly by:

class Bar():

    def __init__(self):
        self.test = 'old'

bar = Bar()
bar_dict = bar.__dict__
print(id(bar.test), id(bar_dict['test'])) # ids are equal

bar_dict['test'] = 'new'
print(bar.test) # new

I guess I still don't understand why this necessarily works though.

Michael Skarn
  • 65
  • 1
  • 7
  • 5
    How could it not? Dictionaries are mutable, so like all other mutable objects, assignments duplicate references; after you perform `a = {}; b = a`, changes to `b` change `a` as well; this is just another case of the same rule. – Charles Duffy Jan 08 '21 at 21:43
  • 2
    You haven't made a copy of the dictionary. `bar_dict['items']` is equivalent to `bar.items` – Barmar Jan 08 '21 at 21:44
  • Because it's the same object. You are not returning a copy of the dictionary but a reference to it. – Chrispresso Jan 08 '21 at 21:44
  • ...so it's very tempting to close this as a duplicate of [python: changes to my copy variable affect the original variable](https://stackoverflow.com/questions/19951816/python-changes-to-my-copy-variable-affect-the-original-variable). – Charles Duffy Jan 08 '21 at 21:45
  • Err... no, the original `Foo()` is lost, but not its `__dict__` member. – quamrana Jan 08 '21 at 21:48

0 Answers0