I have a python code snippet here:
import copy
class Foo(object):
bar = dict()
def __init__(self, bar):
self.bar = bar
def loop(self):
backup = copy.deepcopy(self)
backup.bar[1] = "1"
for i in range(0, 10):
print "BACKUP BAR IS: ", backup.bar
self.bar[1] = "42"
self.bar = backup.bar
a = Foo({1:"0"})
a.loop()
This prints out BACKUP BAR IS: {1: '1'} the first two times, but then it starts to print out BACKUP BAR IS: {1: '42'} the next eight times. Can anyone tell my how and why this is happening? Doesn't deepcopy completely create a new instance of self? How does the value of backup bar change when we only change the value of "self", which is "a", in this case?
Edit: some have noted that the line self.bar = backup.bar causes the two dicts to point to each other. But, if we do:
a = {1:1}
b = {1:2}
c = {1:3}
a = b
a = c
If a and b indeed point to the same dictionary, then all three values of a, b, c should be equal to c. But instead, a = c = {1:3}, b = {1:2}. So changing the reference of the left hand side doesn't change the reference of the right hand side. Similarly, how would backup.bar be changed if we're only changing self.bar?
Setting self.bar = backup.bar does not mutate the dictionary that self.bar is pointing to, nor does it create a copy of backup.bar to assign to self.bar. Rather, it changes the pointer of self.bar to refer to the dictionary at backup.bar, so that they now refer to the same object. Take a look at this demonstration:
In [48]: a = Foo({1: "0"})
In [49]: backup = copy.deepcopy(a)
In [50]: a.bar = backup.bar
In [51]: id(backup.bar)
Out[51]: 140428501511816
In [52]: id(a.bar) # Same object! Alternatively, `a.bar is backup.bar` -> True
Out[52]: 140428501511816
In [53]: backup.bar[1] = "42"
In [54]: a.bar
Out[54]: {1: '42'}
The discrepancy with iteration is explained by @alfasin.
With regard to your question edit, you never change the dictionary that b points to. You're simply changing where a is pointing to twice. a = c does not mean change b = c. It simply means a was pointing to b, now it's pointing to c.
Edit drawings because why not.
a ---> {1: 1}
b ---> {1: 2}
c ---> {1: 3}
After a = b:
a -------- # So long, {1: 1}
|
v
b ---> {1: 2}
c ---> {1: 3}
After a = c, i.e., a points to what c points to:
a ---------------
|
|
b ---> {1: 2} |
c ---> {1: 3} <-|
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With