语句Python 为什么只需一条语句“a,b=b,a”,就能直接交换两个变量?( 二 )


ROT_FOUR
Lifts second, third and forth stack items one position up, moves top down to position four.New in version 3.8.
CPython 应该是以为这几种变量的交换操作很常见 , 因此才提供了专门的优化指令 。 就像 [-5,256] 这些小整数被预先放到了整数池里一样 。
对于更多变量的交换操作 , 实际上则会用到前面说的解包操作:

语句Python 为什么只需一条语句“a,b=b,a”,就能直接交换两个变量?
本文插图
截图中的 BUILD_TUPLE 指令会将给定数量的栈顶元素创建成元组 , 然后被 UNPACK_SEQUENCE 指令解包 , 再依次赋值 。
值得一提的是 , 此处之所以比前面的“a,b=1,2”多出一个 build 操作 , 是因为每个变量的 LOAD_FAST 需要先单独入栈 , 无法直接被组合成 LOAD_CONST 入栈 。 也就是说 , “=”号右侧有变量时 , 不会出现前文中的 LOAD_CONST 一个元组的情况 。
最后还有一个值得一提的细节 , 那几个指令是跟栈中元素的数量有关 , 而不是跟赋值语句中实际交换的变量数有关 。 看一个例子就明白了:
语句Python 为什么只需一条语句“a,b=b,a”,就能直接交换两个变量?
本文插图
【语句Python 为什么只需一条语句“a,b=b,a”,就能直接交换两个变量?】
分析至此 , 你应该明白前文中的结论是怎么回事了吧?
我们稍微总结一下:

  • Python 能在一条语句中实现多重赋值 , 这是利用了序列解包的特性
  • Python 能在一条语句中实现变量交换 , 不需引入中间变量 , 在变量数少于 4 个时(3.8 版本起是少于 5 个) , CPython 是利用了 ROT_* 指令来交换栈中的元素 , 当变量数超出时 , 则是利用了序列解包的特性 。
  • 序列解包是 Python 的一大特性 , 但是在本文的例子中 , CPython 解释器在小小的操作中还提供了几个优化的指令 , 这绝对会超出大多数人的认知


推荐阅读