Why is it that when I do the following:
x = y = {}
Everytime I modify, x like x[1] = 5, I also end up modifying y and vice versa?
Why is it that when I do the following:
x = y = {}
Everytime I modify, x like x[1] = 5, I also end up modifying y and vice versa?
You assign the names x and y to be pointing to one and the same dictionary, what behaviour would you expect?
If you want them to point to different dictionaries, use
x = {}
y = {}
or
x,y = {},{}
Because x and y references the same dictionary.
What happens under the hood:
----- -------
| x | = | ref |-----
----- ------- |
v
------
| {} |
------
^
----- ------- |
| y | = | ref |-----
----- -------
Read about mutable and immutable data:
That is how references works. With x = y = {}, there are two reference variables, but they're both pointing to the same object. With x[1] = 5, you're not really modifying x itself, but rather, the object referred to by x. This is the same object referred to by y, unless you set x and/or y to refer to new objects.
Variables on Python don't work like "boxes" (where you put objects), but as "labels" (where you assign names to objects).
So when you do:
x = y = {}
You are really saying to Python:
I want to call {} as x and y.
Another way to understand this is that the {} syntax is just a shortcut for dict(), which simply returns a new Dict object. So another way to see would be:
x = y = dict()
This returns just one dict object, and assigns two names to it (x and y).
As the other answers say, the original gotcha happens because you're assigning a reference. The next level of confusion is when you do something like this:
a = [[1]]
b = a[:] # You might think [:] will protect you from the original gotcha.
a[0][0] = 2
print b[0][0] # It's 2...why did this change?
It changed because the a[:] slice is actually copying a reference to a[0]. In other words, even though a and b refer to different lists because you used [:], the first element in each is referring to the same list. It's the original problem in a new form. The correct approach here is to do
import copy
a = [[1]]
b = copy.deepcopy(a)
a[0][0] = 2
print b[0][0] # 1