在編程中,一旦提到變量值的交換,腦海中最早浮現的作法就是引入一個臨時變量做爲媒介來作,來看看具體的實現。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。
看到這裏感受序列分解彷佛有點相似於正則表達式的模式匹配。
雖然只是小小的變量值的交換,但本質也是由需求和語言自身特性決定的。學會一些必要的技巧,將會幫助咱們寫出更高質量的代碼。