大家好,我是辰哥~
Lambda 函數是 Python 中的匿名函數。當你需要完成一件小工作時,在本地環境中使用它們可以讓工作得心應手。有些人将它們簡稱為 lambdas,它們的文法如下:
lambda arguments: expression
複制
lambda
關鍵字可以用來建立一個 lambda 函數,緊跟其後的是參數清單和用冒号分割開的單個表達式。例如,
lambda x: 2 * x
是将任何輸入的數乘2,而
lambda x, y: x+y
是計算兩個數字的和。文法十分直截了當,對吧?
假設您知道什麼是 lambda 函數,本文旨在提供有關如何正确使用 lambda 函數的一些正常準則。
# 1. 不要傳回任何值
看看文法,您可能會注意到我們在 lambda 函數中并沒有傳回任何内容。這都是因為 lambda 函數隻能包含一個表達式。然而,使用
return
關鍵字會構成不符合規定文法的語句,如下所示:
>>> 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 "<input>", line 1
sorted(integers, key=lambda x: return x[-1])
^
SyntaxError: invalid syntax
複制
該錯誤可能是由于無法區分表達式和語句而引起的。像是包含
return
、
try
、
with
以及
if
的語句會執行特殊動作。然而,表達式指的是那些可以被計算出一個值的表達,例如數值或其他 Python 對象。
通過使用 lambda 函數,單個表達式會被計算為一個值并且參與後續的計算,例如由
sorted
函數排序。
# 2. 不要忘記更好的選擇
lambda 函數最常見的使用場景是将它作為一些内置工具函數中
key
的實參,比如上面展示的
sorted()
和
max()
。根據情況,我們可以使用其他替代方法。思考下面的例子:
>>> 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)
複制
在資料科學領域,很多人使用 pandas 庫來處理資料。如下所示,我們可以使用 lambda 函數通過
map()
函數從現有資料中建立新資料。除了使用 lambda 函數外,我們還可以直接使用算術函數,因為 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 函數誤認為是簡單函數的另一種聲明方式,您可能也見過有人像下面這麼做:
>>> doubler = lambda x: 2 * x
>>> doubler(5)
10
>>> doubler(7)
14
>>> type(doubler)
<class 'function'>
複制
對 lambda 函數命名的唯一作用可能是出于教學目的,以表明 lambda 函數的确是和其他函數一樣的函數——可以被調用并且具有某種功能。除此之外,我們不應該将 lambda 函數指派給變量。
為 lambda 函數命名的問題在于這使得調試不那麼直覺。與其他的使用正常
def
關鍵字建立的函數不同,lambda 函數沒有名字,這也是為什麼有時它們被稱為匿名函數的原因。思考下面簡單的例子,找出細微的差別:
>>> inversive0 = lambda x: 1 / x
>>> inversive0(2)
0.5
>>> inversive0(0)
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 1, in <lambda>
ZeroDivisionError: division by zero
>>> def inversive1(x):
... return 1 / x
...
>>> inversive1(2)
0.5
>>> inversive1(0)
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 2, in inversive1
ZeroDivisionError: division by zero
複制
- 當您的代碼存在關于 lambda 函數的問題(即 inversive0),Traceback 錯誤資訊隻會提示您 lambda 函數存在問題。
- 相比之下,使用正常定義的函數,Traceback會清晰地提示您有問題的函數(即 inversive1)。
與此相關,如果您想多次使用 lambda 函數,最佳實踐是使用通過
def
定義的允許使用文檔字元串的正常函數。
# 4. 不要忘記清單推導式
有些人喜歡将 lambda 函數和高階函數一起使用,比如
map
或
filter
。思考下面用法示例:
>>> # 建立一個數字清單
>>> numbers = [2, 1, 3, -3]
>>> # 使用帶有 lambda 函數的 map 函數
>>> list(map(lambda x: x * x, numbers))
[4, 1, 9, 9]
>>> # 使用帶有 lambda 函數的 filter 函數
>>> list(filter(lambda x: x % 2, numbers))
[1, 3, -3]
複制
我們可以使用可讀性更強的清單推導式代替 lambda 函數。如下所示,我們使用清單推導式來建立相同的清單對象。如您所見,與清單推導式相比,之前将
map
或
filter
函數與 lambda 函數一起使用更麻煩。是以,在建立涉及高階函數的清單時,應考慮使用清單推導式。
>>> # 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 函數可能會犯的四個常見錯誤。通過避免這些錯誤,您應該能在代碼中正确使用 lambda 函數。
使用 lambda 函數的經驗準則是保持簡單以及隻在本地使用一次。
原文位址: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
- EOF -