0

Consider the following code:

aa=2
bb=aa
aa=4
print(bb) # displays 2

list1=[0]
list2=list1
list1[0]=5
print(list2) # displays [5]

As we see, the behavior is different from the variable containing number and list. I know that in the case of the numbers, when I do:

aa=4

I am telling to Python to create a new memory slot and putting the integer 4 in it. So before this line, bb and aa were referring to the same memory slot but not anymore after this line. bb still refers to the original memory slot containing the value 2 and it is why it hasn't been "updated".

For the list on the other hand, everything is the same before the following line

list1[0]=5

But right after this line, the value contained in the memory slot where list1 and list2 both refers to is changed. This is why list2 will also be changed after.

My questions:

Is the notion of mutable/unmutable object exactly related to this behavior ? In practice, for any mutable object, the same kind of behavior as the one for the list here would occur: if I change the value of an object a, then all object that were assigned to it will also be updated. But for unmutable object, if I change the value of this object a, all other object that were assigned to it before will not have been updated or it is simply impossible to change the value of a at all (like for tuples for instance).

Second but very highly related question. What confused me is that while being unmutable, numbers can be "modified" in the sense that the following code works:

a=2
a=3

Even though I know in practice a new memory is created at the second line (and the first line creates "an orphan"), this is a kind of specific behavior. For tuples it is simply impossible to modify them. Is there a logic behind this "dissymetry" in the behavior depending on the kind of variable within the unmutable ones ?

StarBucK
  • 209
  • 4
  • 18
  • `a=...` always assigns a new value to the name `a`. Whatever `a` was affiliated with before, that affiliation is now broken and `a` refers to a new object. The object that it previously referred to has not been altered by this. — `list1[0]=...` *does something* with the object referred to by `list1`. It's accessing a property of the object. If you think of `list1` pointing to a memory address, then `list1[0]` points to an offset of that address, modifying it (though that's too C for what's happening in Python really). – deceze Feb 15 '21 at 13:33
  • Try http://www.pythontutor.com to visualise what's going on. – deceze Feb 15 '21 at 13:35
  • @deceze Yes I see. But what confuses me a bit is that python creates new value for numbers. But for tuples it doesn't do this (creating something "new"). I also would like to understand why there is this dissymetry in the design ? Is there a logic reason for that ? – StarBucK Feb 15 '21 at 13:35
  • Clarify what you mean by "creates a new value for numbers [but not for tuples]". – deceze Feb 15 '21 at 13:36
  • The "dissymetry" is simply in *mutable* vs. *immutable* objects. You *can't* mutate an int. You can't have `a = 42; a.set_value(6)` or anything like that to turn `42` into `6`. `42` stays `42`. You can calculate a *new* int and assign it to `a`, e.g. `a = a + 1`, or `a += 1` for short. That's a new object. — But lists are *mutable* containers. You can *add* an item into a list or change an existing item in it. That doesn't make a new list, it just expands the existing list object. – deceze Feb 15 '21 at 13:39
  • @deceze Actually my mistake for this I got confused by something. Thanks. But just one last question to check. Do you agree that: if a is an object and b=a. Then **in general** modifying a (i.e saying a=something_else) will have an impact on b IF AND ONLY IF the object is mutable. Otherwise it won't as unmutable object a new reference will be created. – StarBucK Feb 15 '21 at 13:41
  • I would like to get the most general connection with concept of mutability. Without being restricted to numbers or list. The real general vision. – StarBucK Feb 15 '21 at 13:41
  • Not seeing different behavior. If numbers were mutable and you did `5 = 2` then all the variables in your program that were previously 5 would now be 2. – stark Feb 15 '21 at 13:43
  • No. `a=something_else` will ***never*** impact `b`, since you're *assigning a new object to `a`*. It's not that the names `a` and `b` are somehow connected by doing `b = a`; they just happen to point to the same object, and mutating that object is seen by both, because they see the same object. When assigning another object to `a`, then it doesn't "see" the old object anymore. – deceze Feb 15 '21 at 13:43
  • @deceze hmm but then what confuses me is that for a **mutable** object, I should be allowed to modify the *value* stored without modifying the id. Thus what confuses me is that when i did b=a, if b and a pointed to the same object and that the value stored in a has been modified I am confused why conceptually it doesn't modify b. Do you see my confusion ? isn't it actually the kind of thing happening for list contents ? – StarBucK Feb 15 '21 at 13:47
  • It's unclear what specific example you're referring to. – deceze Feb 15 '21 at 13:52
  • 1
    Maybe to break it down. `[]` says to create a new object somewhere in memory. `a = []` says to let `a` refer to the object created in memory. `b = a` says to let `b` refer to the object that `a` is referring to. `a[0] = ...` mutates the object referred to by both. There's only one object, and it's mutated, and two different names refer to that object. `a = something_else` now says to let `a` refer to the object `something_else`. This didn't mutate the list, and `b` is still referring to that first list object. `a` now just refers to something else. – deceze Feb 15 '21 at 13:58
  • @deceze Oh great. Ok so the double bracket [] does ask to create a **new** object. And when I do var1=var2 it **always** means that var1 refer to object var2 is referring to whatever the variables type are (list, number, whatever else). Those aspects are now more clear thanks. – StarBucK Feb 15 '21 at 14:05
  • @deceze So in the end, the command `a[0]=...` will change the value in the list a without changing `id(a)`. So if `b=a` was here before `print(b)` will also change because `a` changed. On the other hand `a[0]` can also be seen as a number (I assume list of numbers). So `id(a[0])` will change with the affectation, which is consistant with the fact number are immutable. Would you agree with my statement ? – StarBucK Feb 15 '21 at 14:18
  • 1
    Yes. Modifying an element within a list does not change the list's identity. It's still the same list object. However, a different value inside the list is a different value. – deceze Feb 15 '21 at 14:23
  • @deceze Allright. Thanks you helped me a lot. – StarBucK Feb 15 '21 at 14:24

0 Answers0