Python为什么只需一条语句a,b=b,a

技术Python为什么只需一条语句a,b=b,a这篇文章主要讲解了“Python为什么只需一条语句a,b=b,a”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python

本文主要讲解Python为什么只需要一个语句a,b=b,a,本文的讲解内容简单明了,易学易懂。请大家跟着小编的思路去研究学习为什么Python只需要一个语句a,b=b,a!

最明显的例子是多重赋值,即在一条语句中同时给多个变量赋值:

x,y=1,2print(x,y)# result: 12在本例中,赋值运算符“=”右侧的两个数字将存储在一个元组中,该元组将变为(1,2),然后依次解包并赋给“=”左侧的两个变量。

如果我们直接写x=1,2,然后打印出x,或者在“=”的右边写一个元组,我们可以确认这一点:

X=1,2print(x)# result: (1,2)x,y=(1,2)print(x,y)# result: 12一些博客或者微信官方账号文章介绍这个功能的时候,通常会举一个例子,就是基于两个变量,直接交换它们的值:

x,y=1,2x,y=y,xprint(x,y)#结果:21一般来说,交换两个变量的操作需要引入第三个变量。原因很简单。如果你想换两个杯子里的水,你自然需要第三个容器作为中转。

但是,Python不需要中间变量,其形式与前面的解包赋值相同。因为这种形式相似,很多人误以为Python的变量交换操作也是基于拆包操作。

但事实是这样吗?

我搜索了一下,发现有人试图回答这个问题,但是他们的回答不够全面。当然,很多都是错误的答案,更多的人只是知道为什么,却从来不想知道为什么。

先把这篇文章的答案放出来:Python的交换变量操作并不完全基于解包操作,有时是,有时不是!

你觉得这个答案很神奇吗?是不是闻所未闻?

这到底是怎么回事?我们先来看看标题中最简单的两个变量。让我们来看看dis黑仔上编译的字节码:

Python为什么只需一条语句a,b=b,a

上图有两个窗口,可以方便的比较“a,b=b,a”和“a,b=1,2”的区别:

“a,b=b,a”操作:两个LOAD_FAST从局部作用域读取变量的引用并存储到堆栈中,接下来是最关键的ROT_TWO操作,将交换两个变量的引用值,然后两个STORE_FAST将堆栈中的变量写入局部作用域。

“a,b=1,2”操作:第一步,LOAD_CONST将栈上“=”右边的两个数作为元组;第二步,UNPACK_SEQUENCE就是对序列进行解包,然后将解包后的结果写入局部作用域的变量中。

显然,这两种类似的写作形式实际上并没有完成相同的操作。在交换变量的操作中,没有打包和解包的步骤!

ROT_TWO指令是CPython解释器为栈顶的两个元素实现的快捷操作,改变它们指向的引用对象。

还有两个类似的指令ROT_THREE和ROT_FOUR,分别是三个变量和四个变量的快速交换(来自ceval.c文件,最新分支3.9):

Python为什么只需一条语句a,b=b,a

预定义的堆栈顶部操作如下:

Python为什么只需一条语句a,b=b,a

查看官方文件中对这些说明的解释,其中3.8版新增ROT_FOUR:

ROT _ twiswapsthetwootop-most stack

 items.   ROT_THREE  Lifts second and third stack item one position up, moves top down to position three.   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 能在一条语句中实现多重赋值,这是利用了序列解包的特性

  • Python 能在一条语句中实现变量交换,不需引入中间变量,在变量数少于 4 个时(3.8 版本起是少于 5 个),CPython 是利用了 ROT_*  指令来交换栈中的元素,当变量数超出时,则是利用了序列解包的特性。

  • 序列解包是 Python 的一大特性,但是在本文的例子中,CPython 解释器在小小的操作中还提供了几个优化的指令,这绝对会超出大多数人的认知

感谢各位的阅读,以上就是“Python为什么只需一条语句a,b=b,a”的内容了,经过本文的学习后,相信大家对Python为什么只需一条语句a,b=b,a这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/57098.html

(0)

相关推荐

  • 狡猾的狐狸是什么歌,狡猾的狐狸是指什么意思

    技术狡猾的狐狸是什么歌,狡猾的狐狸是指什么意思不论在哪个国家狡猾的狐狸是什么歌、哪个民族,狐狸都是狡猾、奸诈、贪婪的形象。人们没有冤枉它,狐狸生来多疑,诡计多端。如果狐狸遭到猎人的枪击,没被击中,它会采取装死的办法,将身

    生活 2021年10月20日
  • 兼职翻译,英语兼职翻译一般都什么水平

    技术兼职翻译,英语兼职翻译一般都什么水平之前在公司上班的时候兼职翻译,公司的兼职遍布各行各业,其中有个很厉害的公务员兼职,每个月做稿量10万+,甩开一片专职译员。提高英语能力方法和资料都太多了,具体到个人就是只有不断的练

    2021年10月30日
  • Python中如何用Redis

    技术Python中如何用Redis本篇内容主要讲解“Python中如何用Redis”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python中如何用Redis”吧!前面我们都

    攻略 2021年11月27日
  • 减肥最快的运动是什么,有哪些能快速减肥的运动

    技术减肥最快的运动是什么,有哪些能快速减肥的运动请问下减肥最快的运动是什么减肥最快的运动是什么?减肥最快的运动就是你运动起来坚持下去,很快就能瘦。常见的运动方式,快走,跑步,骑单车,跳绳,波比跳。游泳也是效果非常好的减肥

    生活 2021年10月24日
  • 怎么用Python代码批量抠图

    技术怎么用Python代码批量抠图这篇文章主要讲解了“怎么用Python代码批量抠图”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么用Python代码批量抠图”吧!1.

    攻略 2021年11月1日
  • 方程式题目五年级,小学五年级数学应用题目什么没有

    技术方程式题目五年级,小学五年级数学应用题目什么没有某小学一班植树48棵,比二班少植树8棵,二班植树多少棵?人民小学食堂运来400千克大米,已经吃了5分之2,还剩多少千克?用一张边长20厘米的正方形纸,裁剪粘贴成一个无盖

    生活 2021年10月23日