Python 元组(a,b)=(b,a)中成员的交换在内部是如何工作的?

Python 元组(a,b)=(b,a)中成员的交换在内部是如何工作的?,python,tuples,python-internals,iterable-unpacking,Python,Tuples,Python Internals,Iterable Unpacking,a和b值的交换在内部是如何工作的?它肯定没有使用temp变量。Python将右侧表达式与左侧赋值分开。首先计算右侧,结果存储在堆栈上,然后使用再次从堆栈中获取值的操作码指定左侧名称 对于包含2个或3个项的元组分配,Python直接使用堆栈: In [55]: a = 5 In [56]: b = 6 In [57]: (a, b) = (b, a) In [58]: a Out[58]: 6 In [59]: b Out[59]: 5 在这两个变量之后(将一个值从一个变量推送到堆栈上)

a和b值的交换在内部是如何工作的?它肯定没有使用temp变量。

Python将右侧表达式与左侧赋值分开。首先计算右侧,结果存储在堆栈上,然后使用再次从堆栈中获取值的操作码指定左侧名称

对于包含2个或3个项的元组分配,Python直接使用堆栈:

In [55]: a = 5

In [56]: b = 6

In [57]: (a, b) = (b, a)

In [58]: a
Out[58]: 6

In [59]: b
Out[59]: 5
在这两个变量之后(将一个值从一个变量推送到堆栈上),堆栈顶部保存
[a,b]
。交换堆栈顶部的两个位置,因此堆栈的顶部现在有
[b,a]
。然后,这两个函数取这两个值,并将它们存储在赋值左侧的名称中。第一个
STORE\u FAST
弹出堆栈顶部的值并将其放入
a
,下一个再次弹出,将值存储在
b
中。之所以需要轮换,是因为Python保证左侧目标列表中的赋值是从左到右完成的

对于3个名称的赋值,随后执行
ROT_TWO
,以反转堆栈上的前三项

对于较长的左侧赋值,将构建一个显式元组:

>>> import dis
>>> def foo(a, b):
...     a, b = b, a
... 
>>> dis.dis(foo)
  2           0 LOAD_FAST                1 (b)
              3 LOAD_FAST                0 (a)
              6 ROT_TWO             
              7 STORE_FAST               0 (a)
             10 STORE_FAST               1 (b)
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE        
这里使用带有
[d,c,b,a]
的堆栈来构建一个元组(按相反顺序,再次从堆栈中弹出,将生成的元组推到堆栈上),然后再次从堆栈中弹出元组,将元组中的所有元素再次推回到堆栈上,以进行
存储\u FAST
操作


后者可能看起来是一个浪费的操作,但赋值的右侧可能完全不同,一个可能会生成元组的函数调用,因此Python解释器不做任何假设,总是使用
UNPACK\u序列
操作码。即使对于两个和三个名称分配操作,它也会使用两个或三个参数替换
构建元组
/
解包序列
组合,并使用上述
ROT_two
ROT_two
操作码来提高效率。

您可能会感兴趣的是查看代码的反汇编。Spoliers:使用字节码指令。旋转需要+1,因为Python保证从左到右完成左侧目标列表中的赋值。。我不知道。
>>> def bar(a, b, c, d):
...     d, c, b, a = a, b, c, d
... 
>>> dis.dis(bar)
  2           0 LOAD_FAST                0 (a)
              3 LOAD_FAST                1 (b)
              6 LOAD_FAST                2 (c)
              9 LOAD_FAST                3 (d)
             12 BUILD_TUPLE              4
             15 UNPACK_SEQUENCE          4
             18 STORE_FAST               3 (d)
             21 STORE_FAST               2 (c)
             24 STORE_FAST               1 (b)
             27 STORE_FAST               0 (a)
             30 LOAD_CONST               0 (None)
             33 RETURN_VALUE