-3

In the following program, if a is referring to the value in b while b is referring to the value 0, then ultimately a is dependent on the value that b is referring to a = b, right? So using this analogy if I change the value that b is storing, then ultimately a should refer to the same value as that of b as well, but when I make these changes, I do not get the expected results that is the value in a is unaffected, hence where am I misinterpreting then?

a = b = 0   
print(a, b)   
b = 1   
print(a, b)

However if I re-write my program:

a = b = []
print(a, b)
b.append(1)
print(a, b)

Then we see that the value of a significantly changes as b is changed, Why?

  • 2
    Recommended reading: https://nedbatchelder.com/text/names.html. In your second example the value of `a` *doesn't* change. – jonrsharpe Feb 15 '21 at 17:04
  • This happens for lists not for integers. Lists store the address, so copying one list to another is like copying the address of the list. But for integers you're copying the value not the address – Aven Desta Feb 15 '21 at 17:05
  • Your second example doesn't work for me: https://wandbox.org/permlink/t4MDXYW0QEXPPKEu An assignment changes the reference, not the value. After `a = b = []` both variables reference the same object. After `b = 1` it references a new, different object. `b.append(1)` changes the object, not the reference. – Thomas Sablik Feb 15 '21 at 17:05
  • 1
    @AvenDesta **the type is irrelevant**. Both examples work the same – juanpa.arrivillaga Feb 15 '21 at 17:06
  • 1
    "Then we see that the value of a significantly changes as b is changed, Why?" No, **it doesn't**. – juanpa.arrivillaga Feb 15 '21 at 17:06
  • I am really sorry, I needed to use the ```append``` method for ```lists``` in the second example. – Malik Ebad Ullah Feb 15 '21 at 17:08
  • In python `variables` does not contain anything, they just point to the `object`. Here `a`, `b` point to the same `int` objeect with value `0`. When you perform `b=1` another int object is created with value `1`. Now `b` is pointing to the newly created object, but `a` still pointing to the previous object. – Epsi95 Feb 15 '21 at 17:08
  • 2
    @MalikEbadUllah that is completely different. `.append` is a mutator method, simple assignment is not. – juanpa.arrivillaga Feb 15 '21 at 17:10
  • Read https://www.python-course.eu/python3_deep_copy.php – Epsi95 Feb 15 '21 at 17:10
  • @Epsi95 But ```a=b``` right, so if ```b``` is pointing to a new object, then why isn't ```a``` also pointing there? – Malik Ebad Ullah Feb 15 '21 at 17:18
  • 1
    @MalikEbadUllah why would it? `a = b` does not "link" *variables*. `a = ` simply assigns the object that `` evaluates to to `a`. The fact that you simply reference another variable as the expression doesn't matter. You never re-assigned `a`. It is still referring to the object you last told it to refer to, and will continue to until you re-assign it. Read https://nedbatchelder.com/text/names.html – juanpa.arrivillaga Feb 15 '21 at 17:19
  • Yes, in the second case `a` and `b` both point to list `[]`. Now when you are doing `b.append(1)` this is happening inside list, but the outer `list container` is not getting changed. So `a` and `b` are completely oblivious to the fact that `[]` is growing. It is when you ask `len(a)` it will fetch the property from `[]` and tell that it's size is increased. – Epsi95 Feb 15 '21 at 17:22
  • Think variable in python just a representative of actual objects, their job is to just point. That is why they can point to anything i.e. any type of object. – Epsi95 Feb 15 '21 at 17:24
  • TLDR; An assignment breaks the link between variable and object: https://wandbox.org/permlink/a4y4LxUHtH2GW1Oh – Thomas Sablik Feb 15 '21 at 17:26

1 Answers1

-2

Because integers aren't mutable. When you reassign one, you're not changing the object that both a and b point to, you're making b reference a different object.

Try this variation:

a = b = [0]
print(a, b)   
b[0] = 1
print(a, b)
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • 5
    mutability is irrelevant. Simple assignment (like in the quesiton) will never mutate, and both examples above work the same – juanpa.arrivillaga Feb 15 '21 at 17:05
  • @juanpa.arrivillaga assignment to an element of a list will indeed mutate the list, by changing the object it contains. – Mark Ransom Feb 15 '21 at 17:07
  • But that isn't really "assigment" in the sense the OP is using it. It's very imporant to note that the OP's examples work exactly the same. EDIT, my point being, this statement: "When you reassign one, you're not changing the object that both a and b point to, you're making b reference a different object." applies to lists... it applies to *all objects* because it is merely the semantics of assignment, which doesn't care about the type of the objects involved – juanpa.arrivillaga Feb 15 '21 at 17:09
  • OP just edited the question and is now using ``b.append(1)`` which changes the nature of the question significantly. – Mike Scotty Feb 15 '21 at 17:10
  • @juanpa.arrivillaga sorry, when I wrote my answer there was only one example, the first one. The second one was edited in. And my example shows how assignment can mutate a list, even if the OPs example does not use assignment. – Mark Ransom Feb 15 '21 at 17:11
  • 1
    It's unrelated to `a` and `b` being numbers or lists. This _"When you reassign one, you're not changing the object that both a and b point to, you're making b reference a different object."_ is true for all types. – Thomas Sablik Feb 15 '21 at 17:12
  • @ThomasSablik it's *very* related, for `int` it's impossible for assignment to change both variables but for `list` it's trivial. Notice that the assignment in my example reassigns an *element* of the list, not the whole list – Mark Ransom Feb 15 '21 at 17:14
  • Are you trying to tell that the behavior will be different for different types? Every type behaves the same when reassigned. – Thomas Sablik Feb 15 '21 at 17:15
  • 1
    @MarkRansom no, it is **never** possible for variable assignment to change both variables, ever. You are talking about item-assignment, which is just a call to some hook, ultimately (`__setitem__`) which can have arbitrary effects. Your statement, "Because integers aren't mutable. When you reassign one, you're not changing the object that both a and b point to, you're making b reference a different object." strongly implies that for mutable objects, re-assigning the variable *will* change, just like the OP's original text incorrectly implied – juanpa.arrivillaga Feb 15 '21 at 17:15
  • @juanpa.arrivillaga mutable objects can be mutated. Why is that even controversial? With a `list` you can accomplish it with reassignment of individual elements. – Mark Ransom Feb 15 '21 at 17:17
  • 1
    @MarkRansom mutable objects can be mutated, **variable assignment never mutates**. `a = b` will **never mutate**, regardless of the types. – juanpa.arrivillaga Feb 15 '21 at 17:18
  • 1
    The question _"Why is the value in a not affected by the change in b?"_ is unrelated to numbers as OP proved by mistake with a wrong example with lists: https://wandbox.org/permlink/8ExRZAiLBkwQUTvr – Thomas Sablik Feb 15 '21 at 17:18
  • @juanpa.arrivillaga I'll agree with that statement except for one thing - I gave a counter-example. Yes, perhaps the assignment is converted to a `__setitem__` call under the covers, but that's an implementation detail. It's still structured as an assignment in the source. – Mark Ransom Feb 15 '21 at 17:27
  • 1
    But your counter example doesn't reassign `b`. It reassigns an element in the list. `a` and `b` are both referencing the same list and changing elements in the list won't change the references in `a` or `b`. That's the difference between shallow copy and deep copy. – Thomas Sablik Feb 15 '21 at 17:29
  • 1
    @MarkRansom that is not an implementation detail, that is part of the data model. It's not a counter-example, because it isn't *variable assignment* which is what I'm talking about, and what the OP originally talked about, and what your text heavily implies. – juanpa.arrivillaga Feb 15 '21 at 17:31