0

I have used Python for a long time but I don't know how objects and the memory really work.

Until a few days ago, I thought that alpha = gamma made a variable whose name was alpha and saved in it a copy of gamma, without linking the variables to each other. However, I have recently noticed that that doesn't happen. Both variables actually point to the same object. Nevertheless, the variables become independent when you change the data in one of them (depending on the variables).

There are many other cases in which variables don't behave like you would expect. This is an example I came upon:

>>> grid1=[[0]*4]*4
>>> grid2=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
>>> grid1 == grid2
True
>>> grid1[2][3]+=1
>>> grid2[2][3]+=1
>>> grid1
[[0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1]]
>>> grid2
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 0, 0]]

I have tried to find more information about how = and other commands treat variables and found some threads, but I have many questions whose answer I don't know yet:

  • Why did the behavior shown above with the lists take place?
  • What should be done in order to avoid it (make grid1 behave like grid2)?
  • Does this have anything to do with the modifiability of the variables? What does it really mean for a variable to be modifiable?
  • When are variables the same object or different ones? How do you know if a command creates a separate variable or not (x+=y vs x = x + y, append vs +)?
  • Is there an == which would have returned false in the example above (is wouldn't work, those two variables were created in different steps and independently so they won't be in the same place in the memory) because in grid1 all lists were in the same place in the memory while in grid2 they were independent?

I haven't been able to find the answers to those questions anywhere, could anyone give a brief answer to the questions or provide a reference which explained these concepts? Thanks.

1 Answers1

0
  1. Why did the behavior shown above with the lists take place?

    Because lists and other mutable collections do not create a new object when you set them to a variable.

  2. What should be done in order to avoid it (make grid1 behave like grid2)?

    grid1=[[[0] for _ in range(4)] for _ in range(4)] would make it work as you want. This is because it actually creates a new list each time instead of duplicating it (like [[0]*4]*4 does).

  3. Does this have anything to do with the modifiability of the variables? What does it really mean for a variable to be modifiable?

    Collections such as strings are immutable so when you do a = "hi";b = a; b += "!" b is set to a new string that copies a and then to a new string that copies b and adds "!".
    Lists instead operate on the same object so when you do a = [];b = a;b.append(1) b is set to a and then it appends 1 to b (which references a in memory).

  4. When are variables the same object or different ones? How do you know if a command creates a separate variable or not (x+=y vs x = x + y, append vs +)?

    It Depends more on the data structure rather than on the operator or method.
    Mutable types: list, set, dict.
    Immutable types: tuple, frozenset, string.

  5. Is there an == which would have returned false in the example above (is wouldn't work, those two variables were created in different steps and independently so they won't be in the same place in the memory) because in grid1 all lists were in the same place in the memory while in grid2 they were independent?

    == evaluates the equality of values (i.e. if they contain the same) while is evaluates if both are the same object. (Try testing == and is on two equal lists. In the first case a = [1]; b = [1] and in the second case a = [1]; b = a.
Yadkee
  • 66
  • 1
  • 5