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
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
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)
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)
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:
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
On Line 3, You Are Setting z to y "x,y,z=x,x,y"