对 python 中变量值交换的一些思考

在编程中,一旦提到变量值的交换,脑海中最早浮现的作法就是引入一个临时变量做为媒介来作,来看看具体的实现。python

解决方案

先假设有两个变量x、y,以下:面试

x = 10
y = 20
复制代码

常见方案,定义一个临时变量做为媒介,实现变量值的交换。实现以下:正则表达式

t = x
x = y
y = t
复制代码

pythonic,对于这种需求其实python为咱们提供了一种更方便的解决方案。编程

x, y = y, x
复制代码

从代码上就能够直观的理解此处的意图,即实现x与y变量值的交换。 到这里都很是容易理解,可是接下来咱们须要思考一下:此写法性能如何?为何能够如此便捷地就是实现了变量值交换?数据结构

性能比较

虽然写法简洁方便,可是是否已损耗性能为代价呢?定义两个函数:ide

def swap1():
    x = 1
    y = 2
    t = x 
    x = y
    y = t

def swap2():
    x = 1
    y = 2
    x, y = y, x
复制代码

为了更好的看出性能差别,循环调用分别调用两函数100次(须要在ipython中执行):函数

swap1耗时38µs性能

%time a = [swap1() for _ in range(100)]
复制代码

结果以下:spa

CPU times: user 31 µs, sys: 7 µs, total: 38 µs
Wall time: 67 µs
复制代码

swap2耗时18µscode

%time a = [swap2() for _ in range(100)]
复制代码

结果以下:

CPU times: user 18 µs, sys: 0 ns, total: 18 µs
Wall time: 21 µs
复制代码

能够看出pythonic的写法比简单粗暴的引入新的辅助变量要快不少。写法如此简洁并且性能高,何乐而不为呢。

这有一篇文章 python面试值交换变量值,从底层解释了两种方式性能差别缘由。swap2 经过 ROT_TWO 指令交换两个变量的值确定比执行 LOAD_FAST+STORE_FAST 两条指令效率高。

注:对于两个变量的交换,其实并无用到元组,能够看看这个视频

多些思考

那么下面再思考一个问题:为何python能够用这种写法来赋值呢?

看一些赋值运算符右边的表达式,即 y, x,这实际在python中称为元组的数据结构。咱们能够看到赋值表达式左边是 x, y,那么为何元组能够直接赋值给 x,y 呢?

此处利用了python的一个特性,即任何序列(或可迭代的对象)均可以经过简单的赋值操做分解为单独的变量。咱们再来看一个例子:

name, age, mobile = 'polo', 30, '15312210823'
复制代码

执行以上代码即可将name赋值为polo,age赋值为30,phone赋值为15312210823。

延伸扩展

除了以上这种简单序列的拆解,python一样支持其余更复杂的场景,下面来看看多层嵌套变量的分解,例子最直观:

school_name, (student_name, stduent_age, stduent_sex) = '致远中学', ('polo', 18, 'M')
复制代码

也能够支持不定长序列的灵活分解,好比如今有一个班级已排序的学生成绩列表,以下:

scores = [21, 34, 36, 56, 60, 75, 76, 81, 83, 86, 86, 89, 90, 95, 98, 99]
复制代码

咱们的目标获取成绩最大、最小和其余学生的成绩列表,直接经过序列的分解即可快速获得须要的数据:

min_score, *other_scores, max_score = scores
复制代码

这里引入了一种新的写法,*表达式变量轻松分解出中间的可迭代对象并赋值给other_scores,同时将开头和结束的对象分别赋值给min_score和max_score。

看到这里感受序列分解彷佛有点相似于正则表达式的模式匹配。

总结

虽然只是小小的变量值的交换,但本质也是由需求和语言自身特性决定的。学会一些必要的技巧,将会帮助咱们写出更高质量的代码。

相关文章
相关标签/搜索