-1

Question: Could someone explain the output? Why is z equal to 2 in the second print()?

Code:

x=1
y=2
x,y,z=x,x,y
print(y,x,y,z)
z,y,z=x,y,z
print(x,y,z)

Output:

1 1 1 2
1 1 2
martineau
  • 119,623
  • 25
  • 170
  • 301
  • Because you're setting `z` to `y` and then printing `z` in `print(y,x,y,z)`? – possum Aug 24 '20 at 17:38
  • 1
    After it creates the (second) tuple, `(1, 1, 2)`, it unpacks it in order into `z,y,z`. So first of all it does `z=1` then `y=1`, and then `z=2` overwriting the `1` that it just assigned. – alani Aug 24 '20 at 17:39
  • [This](https://stackoverflow.com/questions/8587236/how-does-variable-swapping-work-internally) might help you understand better how variable swapping works. It's a matter of pushing and popping from a queue. – Rashid 'Lee' Ibrahim Aug 24 '20 at 17:41
  • 1
    What is confusing about the code? Why do you think it should *not* be 2? – Mark Tolonen Aug 24 '20 at 17:43
  • @alani how you get the second tuple as (1,1,2) – Arun Upreti Aug 24 '20 at 18:03
  • @MarkTolonen The whole output is absurd. Please explain the whole output – Arun Upreti Aug 24 '20 at 18:05
  • 2
    Again, what exactly do you think is incorrect. Saying "it is wrong, please explain it" doesn't tell us what you think is wrong about it. Basically, explain what you think the the answer should be and why, and then we can correct your thinking :) – Mark Tolonen Aug 24 '20 at 18:31

4 Answers4

1

That's because in Python you can declare and assign multiple variable values in the same line from the left to the right.

x=1
y=2
x,y, ->z<- =x,x, ->y<-  then again, assignments are read from left to right, y is 2 and is passed to z, therefore z is now 2.
print(y,x,y,z)
z,y,z=x,y,z
print(x,y,z)

Same example but shorter:

a = 10
b = 99
a, b, c = a, b, b

We are assigning:

10 to a
99 to b

Then respectively a, b, c = 10, 99, 99

In the same note, print takes as much parameter as you'd like dynamically.

Therefore to translate what is going on is this:

x, y, z = 1, 1, 2
print(1, 1, 1, 2)

In your case:

print(y,x,y,z)

Holds the value: 1, 1, 1, 2.

That is because x and y holds 1 whereas value z holds value 2, but y was printed two times, therefore this could also have happened

print(z, z, z, x, y, y, z)

This would output: (2, 2, 2, 1, 1, 1, 2)

Afterwards, in your code

z, x, y = 1, 1, 2

  print(1, 1, 2)
1

You can read about tuples in the tutorial section Tuples and Sequences. In your code tuples are being created and unpacked.

For example, before that second assignment, z is 2.

z,y,z=x,y,z

Here, python created a tuple (1,1,2) from the right hand side, then unpacked on the left. So, z is reassigned to 1, y is reassigned to 1... but then z is reassigned a second time to 2, overwriting the first assignment.

When you write x,y,z you create a tuple from the objects referenced by those variables. Those object now have an additional reference from both the variable and the tuple. And as soon as that tuple is created, it doesn't care what happens to those variables. It has no memory of them, only what that referenced.

The script, with running commentary

x=1
y=2
x,y,z=x,x,y        # create tuple (1,1,2) from the right hand side x,x,y
                   # then unpack left hand side: x=1; y=1; z=2.
print(y,x,y,z)
z,y,z=x,y,z        # create a tuple (1,1,2) from the right hand side x,y,z
                   # then unpack left hand side: z=1; y=1; z=1 (overwriting z)
print(x,y,z)
tdelaney
  • 73,364
  • 6
  • 83
  • 116
1

Python tuple assignment uses a stack, so assuming x=1 and y=2:

x,y,z=x,x,y

translates abstractly to:

push x (value 1) on stack:    top_of_stack(TOS) -> 1
push x (value 1) on stack:    TOS -> 1, 1
push y (value 2) on stack:    TOS -> 2, 1, 1
reverse top 3 stack entries:  TOS -> 1, 1, 2
pop stack and store in x (x=1)  TOS -> 1, 2
pop stack and store in y (y=1)  TOS -> 2
pop stack and store in z (z=2)  TOS -> empty

final result is x=1, y=1, z=2, next line:

z,y,z=x,y,z

pushes x,y,z (1,1,2), then loads z=1, then y=1, then z=2 (overwriting z=1).

Here's the actual disassembly with comments:

>>> dis.dis('x=1;y=2;x,y,z=x,x,y;z,y,z=x,y,z')
  1           0 LOAD_CONST               0 (1)     # load constant 1
              2 STORE_NAME               0 (x)     # assign to x
              4 LOAD_CONST               1 (2)     # load constant 2
              6 STORE_NAME               1 (y)     # assign to y
              8 LOAD_NAME                0 (x)     # push x on stack (1)
             10 LOAD_NAME                0 (x)     # push x again on stack (1)
             12 LOAD_NAME                1 (y)     # push y on stack (2)
             14 ROT_THREE                          # two instructions reverse stack
             16 ROT_TWO                            # .. 2,1,1 becomes 1,1,2
             18 STORE_NAME               0 (x)     # pop x=1
             20 STORE_NAME               1 (y)     # pop y=1
             22 STORE_NAME               2 (z)     # pop z=2
             24 LOAD_NAME                0 (x)     # push x (1)
             26 LOAD_NAME                1 (y)     # push y (1)
             28 LOAD_NAME                2 (z)     # push z (2)
             30 ROT_THREE                          # reverse stack
             32 ROT_TWO                            #  2,1,1 becomes 1,1,2
             34 STORE_NAME               2 (z)     # pop z=1  <---
             36 STORE_NAME               1 (y)     # pop y=1      \
             38 STORE_NAME               2 (z)     # pop z=2 (overwriting previous)

You can also think of this more abstractly as:

  1. Compute the right side values first.
  2. Assign left-to-right to variables on right.

So:

x=1
y=2
x,y,z=x,x,y

Means:

# x,y,z=1,1,2
x=1
y=1
z=2

Then:

z,y,z=x,y,z

Means:

# z,y,z = 1,1,2
z=1
y=1
z=2   # overwriting previous z=1
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
-1

On Line 3, You Are Setting z to y "x,y,z=x,x,y"

AriesNinja
  • 55
  • 10
  • The question was about the _second_ `print`, not the _first_ one. Your answer doesn’t explain `z,y,z=x,y,z`. – Sebastian Simon Aug 26 '20 at 00:51
  • This is because since you are setting z to 2 values in the tuple, it is automatically assigning the variable to the second value, which is itself. – AriesNinja Aug 26 '20 at 16:19