2

Can anyone explain to me why on test1, nums is [[0,0],[-1,-1],[0,0],[0,0]] but not on test2? as my understand python for xx in xxx is pretty much like for loop in any other language and take element by element. So what is different between using unpack in for loop and not? Thank you

test([[0,0],[0,0],[0,0],[0,0]])
test2([[0,0],[0,0],[0,0],[0,0]])
def test1(self, nums):
    ctn = 0
    for e in nums:
        ctn += 1
        u, v = e
        if ctn == 2:
            e[0] = e[1] = -1
    print(nums)  #[[0,0],[-1,-1],[0,0],[0,0]]

def test2(self, nums):
    ctn = 0
    for u, v in nums:
        ctn += 1
        if ctn == 2:
            u = v = -1
    print(nums)  #[[0,0],[0,0],[0,0],[0,0]]
A.Lee
  • 265
  • 2
  • 9

4 Answers4

2

The variables u and v are references to the elements in the sublist, without any reference to the sublist itself. When you change either value, it does not cause any side effects.

However, e is a reference to the sublist itself. When you index into e and change its values, you are performing an assignment in the sublist itself, and thus causes side effects (changing the value in the original list).

Dillon Davis
  • 6,679
  • 2
  • 15
  • 37
  • `u` and `e` act as references to the items in the list, the way you've added emphasis might be misleading – juanpa.arrivillaga Mar 07 '19 at 04:41
  • so why e is a reference but u and v is "new" variable from list? i guess another way to say is why e is not something e = [0,0] that store the value from nums sublist? – A.Lee Mar 07 '19 at 05:25
  • @DillonDavis absolutely incorrect. There *are no primitive types* in Python. *Everything* is an object, and the evaluation strategy doesn't not change depending on the type of the object. [See this question](https://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference). Suffice it to say, Python is neither call by reference nor call by value. It is ["call by sharing"](https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing), although that is a little used term. This is the same evaluation strategy of most modern languages, e.g. Python, Java, Javascript, Ruby. – juanpa.arrivillaga Mar 07 '19 at 05:38
  • But it is *very important* to understand that whatever you call it, the evaluation strategy *does not depend on the type of the object* Another good link to read: https://nedbatchelder.com/text/names.html – juanpa.arrivillaga Mar 07 '19 at 05:40
  • "Copy on write" is totally irrelevant here. Not sure what you are getting at, nor what you code snippet is supposed to show. Note, small integers are cached, i.e., in Python `int` objects in the range -2-255 are *singletons*. That is an implementation detail, though, that shouldn't be relied upon. Anyway, "u and v do not reference into the list", I'm not sure what that's supposed to mean, but `u` and `v` are *definitely references to the same object in the list*. – juanpa.arrivillaga Mar 07 '19 at 05:43
  • And what point are you trying to make? Note, this doesn't work with say, 500, so write a line `x = 500`, then write `l = [500]` on another line. The `print(id(x))` and `print(id(l[0]))` (I say write on another line because various optimizations for immutable types may make the interpreter optimize this, usually with `int` and `str` literals in the same block) – juanpa.arrivillaga Mar 07 '19 at 05:46
  • Again, *please please please* read the links I've provided to you. Python doesn't have anything even approaching call by reference. – juanpa.arrivillaga Mar 07 '19 at 05:48
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/189570/discussion-between-dillon-davis-and-juanpa-arrivillaga). – Dillon Davis Mar 07 '19 at 05:48
1

Variable hold references in Python. That means that when you assign a mutable object (a list is) to a variable and change the object through that variable you change the original object. That is the reason why test1 does change the original list.

But when you assign to a variable, you do not change the object it previously refered, but only have it point to a new object. As you assign to u and v in test2 you change nothing in the original objects.


When you use e[0] = -1, you do not assign to variable e but actually modify the object pointed to by e

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
0

in the first function u, v =e do nothing,delete it i get the same answer

def test1(nums):
    ctn = 0
    k = []
    for e in nums:
        ctn += 1
        if ctn == 2:
            e[0] = e[1] = -1
    print(nums)

def test2(nums):
    ctn = 0
    for u, v in nums:
        ctn += 1
        if ctn == 2:
            u = v = -1
    print(nums)
Tom.chen.kang
  • 173
  • 2
  • 9
-1

In test2, u and v are temporary copies of the original values in the list. Because they are copies, any changes you make to them will not be reflected in the original list.

Paul M.
  • 10,481
  • 2
  • 9
  • 15