對 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。

看到這裏感受序列分解彷佛有點相似於正則表達式的模式匹配。

總結

雖然只是小小的變量值的交換,但本質也是由需求和語言自身特性決定的。學會一些必要的技巧,將會幫助咱們寫出更高質量的代碼。

相關文章
相關標籤/搜索