牢記“四不要”,寫好 Python 的 Lambda 函數(shù)
↑?關注 + 星標?,每天學Python新技能
后臺回復【大禮包】送你Python自學大禮包
lambda?arguments:?expression
lambda 關鍵字可以用來創(chuàng)建一個 lambda 函數(shù),緊跟其后的是參數(shù)列表和用冒號分割開的單個表達式。例如,lambda x: 2 * x 是將任何輸入的數(shù)乘2,而 lambda x, y: x+y 是計算兩個數(shù)字的和。語法十分直截了當,對吧?
假設您知道什么是 lambda 函數(shù),本文旨在提供有關如何正確使用 lambda 函數(shù)的一些常規(guī)準則。
# 1. 不要返回任何值
看看語法,您可能會注意到我們在 lambda 函數(shù)中并沒有返回任何內容。這都是因為 lambda 函數(shù)只能包含一個表達式。然而,使用 return 關鍵字會構成不符合規(guī)定語法的語句,如下所示:
>>>?integers?=?[(3,?-3),?(2,?3),?(5,?1),?(-4,?4)]
>>>?sorted(integers,?key=lambda?x:?x[-1])
[(3,?-3),?(5,?1),?(2,?3),?(-4,?4)]
>>>?sorted(integers,?key=lambda?x:?return?x[-1])
...?
??File?"",?line?1
????sorted(integers,?key=lambda?x:?return?x[-1])
???????????????????????????????????^
SyntaxError:?invalid?syntax
該錯誤可能是由于無法區(qū)分表達式和語句而引起的。像是包含 return、try、 with 以及 if 的語句會執(zhí)行特殊動作。然而,表達式指的是那些可以被計算出一個值的表達,例如數(shù)值或其他 Python 對象。
通過使用 lambda 函數(shù),單個表達式會被計算為一個值并且參與后續(xù)的計算,例如由 sorted 函數(shù)排序。
# 2. 不要忘記更好的選擇
lambda 函數(shù)最常見的使用場景是將它作為一些內置工具函數(shù)中 key 的實參,比如上面展示的 sorted() 和 max()。根據(jù)情況,我們可以使用其他替代方法。思考下面的例子:
>>>?integers?=?[-4,?3,?7,?-5,?-2,?6]
>>>?sorted(integers,?key=lambda?x:?abs(x))
[-2,?3,?-4,?-5,?6,?7]
>>>?sorted(integers,?key=abs)
[-2,?3,?-4,?-5,?6,?7]
>>>?scores?=?[(93,?100),?(92,?99),?(95,?94)]
>>>?max(scores,?key=lambda?x:?x[0]?+?x[1])
(93,?100)
>>>?max(scores,?key=sum)
(93,?100)
在數(shù)據(jù)科學領域,很多人使用 pandas 庫來處理數(shù)據(jù)。如下所示,我們可以使用 lambda 函數(shù)通過 map() 函數(shù)從現(xiàn)有數(shù)據(jù)中創(chuàng)建新數(shù)據(jù)。除了使用 lambda 函數(shù)外,我們還可以直接使用算術函數(shù),因為 pandas 是支持的:
>>>?import?pandas?as?pd
>>>?data?=?pd.Series([1,?2,?3,?4])
>>>?data.map(lambda?x:?x?+?5)
0????6
1????7
2????8
3????9
dtype:?int64
>>>?data?+?5
0????6
1????7
2????8
3????9
dtype:?int64
# 3. 不要將它賦值給變量
我曾見過一些人將 lambda 函數(shù)誤認為是簡單函數(shù)的另一種聲明方式,您可能也見過有人像下面這么做:
>>>?doubler?=?lambda?x:?2?*?x
>>>?doubler(5)
10
>>>?doubler(7)
14
>>>?type(doubler)
<class?'function'>
對 lambda 函數(shù)命名的唯一作用可能是出于教學目的,以表明 lambda 函數(shù)的確是和其他函數(shù)一樣的函數(shù)——可以被調用并且具有某種功能。除此之外,我們不應該將 lambda 函數(shù)賦值給變量。
為 lambda 函數(shù)命名的問題在于這使得調試不那么直觀。與其他的使用常規(guī) def 關鍵字創(chuàng)建的函數(shù)不同,lambda 函數(shù)沒有名字,這也是為什么有時它們被稱為匿名函數(shù)的原因。思考下面簡單的例子,找出細微的區(qū)別:
>>>?inversive0?=?lambda?x:?1?/?x
>>>?inversive0(2)
0.5
>>>?inversive0(0)
Traceback?(most?recent?call?last):
??File?"",?line?1,?in?<module>
??File?"",?line?1,?in?
ZeroDivisionError:?division?by?zero
>>>?def?inversive1(x):
...?????return?1?/?x
...?
>>>?inversive1(2)
0.5
>>>?inversive1(0)
Traceback?(most?recent?call?last):
??File?"",?line?1,?in?<module>
??File?"",?line?2,?in?inversive1
ZeroDivisionError:?division?by?zero
當您的代碼存在關于 lambda 函數(shù)的問題(即 inversive0),Traceback 錯誤信息只會提示您 lambda 函數(shù)存在問題。
相比之下,使用正常定義的函數(shù),Traceback會清晰地提示您有問題的函數(shù)(即 inversive1)。
與此相關,如果您想多次使用 lambda 函數(shù),最佳實踐是使用通過 def 定義的允許使用文檔字符串的常規(guī)函數(shù)。
# 4. 不要忘記列表推導式
有些人喜歡將 lambda 函數(shù)和高階函數(shù)一起使用,比如 map 或 filter。思考下面用法示例:
>>>?#?創(chuàng)建一個數(shù)字列表
>>>?numbers?=?[2,?1,?3,?-3]
>>>?#?使用帶有?lambda?函數(shù)的?map?函數(shù)
>>>?list(map(lambda?x:?x?*?x,?numbers))
[4,?1,?9,?9]
>>>?#?使用帶有?lambda?函數(shù)的?filter?函數(shù)
>>>?list(filter(lambda?x:?x?%?2,?numbers))
[1,?3,?-3]
我們可以使用可讀性更強的列表推導式代替 lambda 函數(shù)。如下所示,我們使用列表推導式來創(chuàng)建相同的列表對象。如您所見,與列表推導式相比,之前將 map 或 filter 函數(shù)與 lambda 函數(shù)一起使用更麻煩。因此,在創(chuàng)建涉及高階函數(shù)的列表時,應考慮使用列表推導式。
>>>?#?Use?list?comprehensions
>>>?[x?*?x?for?x?in?numbers]
[4,?1,?9,?9]
>>>?[x?for?x?in?numbers?if?x?%?2]
[1,?3,?-3]
# 結論
在本文中,我們回顧了使用 lambda 函數(shù)可能會犯的四個常見錯誤。通過避免這些錯誤,您應該能在代碼中正確使用 lambda 函數(shù)。
使用 lambda 函數(shù)的經(jīng)驗準則是保持簡單以及只在本地使用一次。
原文地址:Master Python Lambda Functions With These 4 Don’ts
原文作者:Yong Cui, Ph.D.
譯文出自:掘金翻譯計劃
本文永久鏈接:https://github.com/xitu/gold-miner/blob/master/article/2020/master-python-lambda-functions-with-these-4-donts.md
譯者:loststar ?校對者:luochen1992
推薦閱讀
