所有代碼均來(lái)自于Python 2.7 版本
對(duì)于交換兩個(gè)值的操作,可能大多數(shù)之前不具備Python基礎(chǔ)的童鞋比較容易寫出以下代碼:
>>> tmp = x
>>> x = y
>>> y = tmp
顯然,這樣寫很不Pythonic,它的確可以工作,但稱不上簡(jiǎn)潔有效。
#在Python中更常見(jiàn)的寫法
>>> x, y = y, x
簡(jiǎn)潔性可以一目了然,那效率又如何呢?
>>> from timeit import Timer
>>> Timer('tmp = x;x = y;y = tmp','x = 2; y = 4').time()
0.0300285 #根據(jù)運(yùn)行環(huán)境不同,結(jié)果可能會(huì)有差異
>>> Timer('x, y = y, x', 'x = 2; y = 4').timeit()
0.0265907
雖然差距不大,但是還是有一點(diǎn)點(diǎn)差距的。(差距不明顯是因?yàn)橹皇且粋€(gè)簡(jiǎn)單的賦值語(yǔ)句,加上計(jì)算機(jī)的計(jì)算速度與日俱增)
那么,在x, y = y, x的背后都發(fā)生了些什么呢?
一般情況下Python語(yǔ)句是從左到右解析一個(gè)語(yǔ)句的,但在賦值操作的時(shí)候,因?yàn)槭怯抑稻哂懈叩挠?jì)算優(yōu)先級(jí),所以需要從右向左解析。
對(duì)于x, y = y, x,它的執(zhí)行順序如下:
- 先計(jì)算右值
y , x(這里是簡(jiǎn)單的原值,但可能會(huì)有表達(dá)式或者函數(shù)調(diào)用的計(jì)算過(guò)程), 在內(nèi)存中創(chuàng)建元組(tuple),存儲(chǔ)y, x分別對(duì)應(yīng)的值; - 計(jì)算左邊的標(biāo)識(shí)符,元組被分別分配給左值,通過(guò)解包(unpacking),元組中第一個(gè)標(biāo)示符對(duì)應(yīng)的值(y),分配給左邊第一個(gè)標(biāo)示符(x),元組中第二個(gè)標(biāo)示符對(duì)應(yīng)的值(x),分配給左邊第二個(gè)標(biāo)示符(y),完成了
x和y的值交換。
需要注意的是當(dāng)左右值和標(biāo)識(shí)符的數(shù)量不等時(shí)會(huì)出現(xiàn)ValueError:
>>> x, y = 1, 2
>>> x, z = y, x, 3
ValueError: too many values to unpack
>>> y, x , a= x, y
ValueError: need more than 2 values to unpack
而當(dāng)左值只有一個(gè)變量的時(shí)候,默認(rèn)將右值打包(pack)成一個(gè)元組(tuple)傳給右值。
>>> x = 1, 2
>>> x
(1, 2)