Python 3.8 新功能,利用海象運算符,提升程序執行效率

海象運算符

這個新運算符 := 能讓我們為表達式中的一個變量賦值,這個符號看起來頗有些類似于海象的眼睛和犬齒。

我們先來看看下面一段代碼:

countries = [“India”, “USA”, “France”, “Germany”]
if len(countries) < 5:
    print ("Length of countries is " + len(countries))

在上面的代碼段中,我們兩次調用了函數 len()。我們可以避免重復計算以提升可讀性嗎?當然可以,我們可對這段代碼進行如下改進:

country_size = len(countries)
if country_size < 5:
   print ("Length of countries is " + country_size)

還有進一步改進的空間嗎?我們可以不用單獨一行來給「country_size」賦值嗎?

if country_size := len(countries) < 5 :
    print ("Length of countries is " + country_size)

這就是 Python 3.8 引入的海象運算符的用武之地。我們可以在 if 語句之中直接執行聲明和賦值操作。我們下面進一步探索該運算符的能力。

代碼行數與復雜度的平衡

先看看以下示例(多次調用一個高成本的函數)

powers = [get_count(), get_count()**2, get_count()**3]

def get_count():
  "Fetches count of records from a database"

上面的示例是通過多次調用一個高成本的函數 get_count() 來填充一個列表。

有了海象運算符的幫助,我們可以避免多次調用函數 get_count(),其具體的功能是將結果存儲到一個變量中,然后我們可在后續的計算中復用同一個變量。

下面演示了海象運算符的用法:

powers =[result:= get_count(), result**2, result**3]

def get_count():
 "Fetches count of records from a database"

從上面的例子可以看到,海象運算符可以減少代碼行數,讓代碼更可讀,因此能簡化代碼審查人員的工作。此外,這也能實現代碼行數和代碼復雜度的平衡。

解決理解低效的問題

employees = []
for id in employee_ids:
employee = fetch_employee(id)
if employee:
  employees.append(employee)

基于一個條件填充列表
上面的示例需要多次執行循環。一開始,我們創建一個空列表,然后在 id 列表上迭代并通過檢查結果是否有效來填充我們創建的列表。

我們可以簡化上面的代碼,將其濃縮為一行:

employees = [result for id in employee_ids if (result:= fetch_employee(id))]
# 使用海象運算符避免低效理解

文件分塊處理

在處理大文件時,我們會將文件分塊讀取。每當讀取一個分塊時,都會檢查它的值,并且該值也是 while 循環的終止條件。

chunk = file.read(256)

while chunk:
  process(chunk)
  chunk = file.read(256)

我們可以在 while 循環表達式中讀取數據以及為要讀取的數據賦值。由此我們就能避免在 while 循環之外顯式地聲明變量。如下示例:

while chunk := file.read(256) :
   process(chunk)

正則表達式匹配

正則表達式匹配是一個兩步式過程。第一步是檢查是否有匹配,第二步是提取匹配的部分。

obj = re.match(info).group(1) if re.match(info) else None
#正則表達式匹配

從上面的代碼可以觀察到,我們在一次匹配中重復計算了 re.match(info)。這會減慢該程序的執行速度,而且數據量越大減慢得越明顯。上面的代碼可以重寫為如下形式,從而避免重復計算:

obj = match.group(1) if match:= re.match(info) else None
#使用 := 的正則表達式匹配

不能使用海象運算符的地方

為變量賦值

a = 5 # 有效
a := 5 # 無效

empty_list = [] # 有效
empty_list := [] # 無效

如上所示,我們不能使用 := 替代 =。海象運算符只能是一個表達式的一部分。

加法/減法賦值
a += 5 # 有效
a :+=5 # 無效
在 lambda 函數中為表達式賦值
(lambda: a:= 5) # 無效
lambda: (a := 5) # 有效但無用
(var := lambda: 5) # 有效
PEP-572 及其爭議

海象預算符的爭議點有很多,下面是其中幾個:

句法變化問題:開發者們為 := 提議了多種替代方案,比如「表達式 -> NAME」、「NAME -> 表達式」、「{表達式} NAME」等等。少數人建議使用現有的關鍵字,其他人則使用了新的運算符。

后向兼容問題:這個特性無法向后兼容,也無法運行在之前的 Python 版本上。

運算符名稱問題:人們建議不要使用「海象運算符」這樣的代號,而是使用「賦值運算符」、「命名表達式運算符」、「成為運算符」等術語,以免人們不明白。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容