python交换三个值得方法非常简单,即b, c, a = a, b, c,一步操作就交换了,那么这是为什么呢?
1. 真相
Python的变量并不直接存储值,而只是引用一个内存地址,交换变量时,只是交换了引用的地址。
先看下面这段程序:
import dis
def test(a, b, c):
b, c, a = a, b, c
return a, b, c
if __name__ == '__main__':
a = 1
b = 2
c = 3
dis.dis(test)
print(test(a, b, c))
运行结果:
字节码
一般来说一个Python语句会对应若干字节码
指令,Python的字节码是一种类似
汇编指令的中间语言,但是一个字节码指令并不是对应一个机器指令(二进制指令),而是对应一段C代码
,而不同的指令的性能不同,所以不能单独通过指令数量来判断代码的性能,而是要通过查看调用比较频繁的指令的代码来确认一段程序的性能。
一个Python的程序会有若干代码块组成,例如一个Python文件会是一个代码块,一个类,一个函数都是一个代码块,一个代码块会对应一个运行的上下文环境以及一系列的字节码指令。
dis模块
dis模块主要是用来分析字节码的一个内置模块,经常会用到的方法是dis.dis([bytesource]),参数为一个代码块,可以得到这个代码块对应的字节码指令序列。
从以上字节码中可以看出变量交换过程主要是ROT_TWO和ROT_THREE指令
的功劳:
查阅python文档可以知道有ROT_TWO (源码1398行),ROT_THREE(源码1406行), ROT_FOUR这样的指令,可以直接交换两个变量、三个变量、四个变量的值。
在python3.4的源码中查阅ceval.c文件可以看到:
TARGET(ROT_TWO) {
PyObject *top = TOP();
PyObject *second = SECOND();
SET_TOP(second);
SET_SECOND(top);
FAST_DISPATCH();
}
TARGET(ROT_THREE) {
PyObject *top = TOP();
PyObject *third = THIRD();
SET_SECOND(third);
FAST_DISPATCH();
}
2. 具体分析b, c, a = a, b, c的交换过程
2.1 从底层分析
2.2 抛弃底层只看表面
Python 会首先计算右侧的表达式 a,b,c,然后将其元组解包并赋值给左侧的变量 b,c,a。这意味着交换操作是原子的,不会出现中间状态。
[参考博客]
https://blog.csdn.net/qq_33414271/article/details/78522235