不理解这段显示元组解包的代码
Don't understand this code showing tuple unpacking
问题:有人可以解释输出吗?为什么z
在第二个print()
中等于2
?
代码:
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)
输出:
1 1 1 2
1 1 2
那是因为在Python中,您可以在同一行中从左到右声明和分配多个变量值。
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)
相同示例但更短:
a = 10
b = 99
a, b, c = a, b, b
我们正在分配:
10 to a
99 to b
然后分别a, b, c = 10, 99, 99
在同一个注释中,打印可以根据需要动态地获取尽可能多的参数。
所以翻译是这样的:
x, y, z = 1, 1, 2
print(1, 1, 1, 2)
你的情况:
print(y,x,y,z)
保留值:1、1、1、2。
那是因为 x 和 y 的值为 1 而值 z 的值为 2,但是 y 被打印了两次,所以这也可能发生
print(z, z, z, x, y, y, z)
这将输出:(2, 2, 2, 1, 1, 1, 2)
之后,在您的代码中
z, x, y = 1, 1, 2
print(1, 1, 2)
您可以在教程部分 Tuples and Sequences 中阅读有关元组的内容。在您的代码中,正在创建和解压缩元组。
例如,在第二次赋值之前,z
是 2
。
z,y,z=x,y,z
在这里,python 从右侧创建了一个元组 (1,1,2)
,然后在左侧解压。因此,z
被重新分配给 1,y
被重新分配给 1... 但是 z
第二次被重新分配给 2,覆盖了第一次分配。
当您编写 x,y,z
时,您会根据这些变量引用的对象创建一个元组。这些对象现在有来自变量和元组的附加引用。一旦该元组被创建,它就不会关心这些变量会发生什么。它没有关于它们的记忆,只有引用的内容。
剧本,附运行评论
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)
在第 3 行,您将 z 设置为 y "x,y,z=x,x,y"
Python 元组分配使用堆栈,因此假设 x=1 和 y=2:
x,y,z=x,x,y
抽象地翻译为:
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
最终结果为 x=1, y=1, z=2, 下一行:
z,y,z=x,y,z
压入 x,y,z (1,1,2),然后加载 z=1,然后加载 y=1,然后加载 z=2(覆盖 z=1)。
这是带有注释的实际反汇编:
>>> 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)
您也可以将其更抽象地理解为:
- 先计算右边的值。
- 将left-to-right分配给右边的变量。
所以:
x=1
y=2
x,y,z=x,x,y
表示:
# x,y,z=1,1,2
x=1
y=1
z=2
然后:
z,y,z=x,y,z
表示:
# z,y,z = 1,1,2
z=1
y=1
z=2 # overwriting previous z=1
问题:有人可以解释输出吗?为什么z
在第二个print()
中等于2
?
代码:
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)
输出:
1 1 1 2
1 1 2
那是因为在Python中,您可以在同一行中从左到右声明和分配多个变量值。
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)
相同示例但更短:
a = 10
b = 99
a, b, c = a, b, b
我们正在分配:
10 to a
99 to b
然后分别a, b, c = 10, 99, 99
在同一个注释中,打印可以根据需要动态地获取尽可能多的参数。
所以翻译是这样的:
x, y, z = 1, 1, 2
print(1, 1, 1, 2)
你的情况:
print(y,x,y,z)
保留值:1、1、1、2。
那是因为 x 和 y 的值为 1 而值 z 的值为 2,但是 y 被打印了两次,所以这也可能发生
print(z, z, z, x, y, y, z)
这将输出:(2, 2, 2, 1, 1, 1, 2)
之后,在您的代码中
z, x, y = 1, 1, 2
print(1, 1, 2)
您可以在教程部分 Tuples and Sequences 中阅读有关元组的内容。在您的代码中,正在创建和解压缩元组。
例如,在第二次赋值之前,z
是 2
。
z,y,z=x,y,z
在这里,python 从右侧创建了一个元组 (1,1,2)
,然后在左侧解压。因此,z
被重新分配给 1,y
被重新分配给 1... 但是 z
第二次被重新分配给 2,覆盖了第一次分配。
当您编写 x,y,z
时,您会根据这些变量引用的对象创建一个元组。这些对象现在有来自变量和元组的附加引用。一旦该元组被创建,它就不会关心这些变量会发生什么。它没有关于它们的记忆,只有引用的内容。
剧本,附运行评论
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)
在第 3 行,您将 z 设置为 y "x,y,z=x,x,y"
Python 元组分配使用堆栈,因此假设 x=1 和 y=2:
x,y,z=x,x,y
抽象地翻译为:
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
最终结果为 x=1, y=1, z=2, 下一行:
z,y,z=x,y,z
压入 x,y,z (1,1,2),然后加载 z=1,然后加载 y=1,然后加载 z=2(覆盖 z=1)。
这是带有注释的实际反汇编:
>>> 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)
您也可以将其更抽象地理解为:
- 先计算右边的值。
- 将left-to-right分配给右边的变量。
所以:
x=1
y=2
x,y,z=x,x,y
表示:
# x,y,z=1,1,2
x=1
y=1
z=2
然后:
z,y,z=x,y,z
表示:
# z,y,z = 1,1,2
z=1
y=1
z=2 # overwriting previous z=1