網(wǎng)站首頁 編程語言 正文
什么是 Python 中的 Lambda 函數(shù)
今天我們來學習 Python 中的 lambda 函數(shù),并探討使用它的優(yōu)點和局限性
Let's do it!
lambda 函數(shù)是一個匿名函數(shù)(即,沒有名稱定義),它可以接受任意數(shù)量的參數(shù),但與普通函數(shù)不同,它只計算并返回一個表達式
Python 中的 lambda 函數(shù)使用以下語法表達:
lambda 參數(shù):表達式
lambda 函數(shù)包括三個元素:
- 關鍵字 lambda:與普通函數(shù)中 def 類似
- 參數(shù):支持傳遞位置和關鍵字參數(shù),與普通函數(shù)一樣
- 正文:處理定參數(shù)的表達式
需要注意的是,普通函數(shù)不同,這里不需要用括號將 lambda 函數(shù)的參數(shù)括起來,如果 lambda 函數(shù)有兩個或更多參數(shù),我們用逗號列出它們
我們使用 lambda 函數(shù)只計算一個短表達式(理想情況下,單行)并且只計算一次,這意味著我們以后不會再復用這個函數(shù)。 通常來說我們會將 lambda 函數(shù)作為參數(shù)傳遞給高階函數(shù)(接受其他函數(shù)作為參數(shù)的函數(shù)),例如 Python 內(nèi)置函數(shù),如 filter()、map() 或 reduce()等
Python 中的 Lambda 函數(shù)如何工作
讓我們看一個簡單的 lambda 函數(shù)示例:
lambda x: x + 1
Output:
<function __main__.<lambda>(x)>
上面的 lambda 函數(shù)接受一個參數(shù),將其遞增 1,然后返回結果
它是以下帶有 def 和 return 關鍵字的普通函數(shù)的更簡單版本:
def increment_by_one(x): return x + 1
到目前我們的 lambda 函數(shù) lambda x: x + 1
只創(chuàng)建一個函數(shù)對象,不返回任何內(nèi)容,這是因為我們沒有為其參數(shù) x 提供任何值(參數(shù))。讓我們先分配一個變量,將它傳遞給 lambda 函數(shù),看看這次我們得到了什么:
a = 2 print(lambda x: a + 1)
Output:
<function <lambda> at 0x00000250CB0A5820>
我們的 lambda 函數(shù)沒有像我們預期的那樣返回 3,而是返回了函數(shù)對象本身及其內(nèi)存位置,可以看出這不是調(diào)用 lambda 函數(shù)的正確方法。要將參數(shù)傳遞給 lambda 函數(shù),執(zhí)行它并返回結果,我們應該使用以下語法:
(lambda x: x + 1)(2)
Output:
3
雖然我們的 lambda 函數(shù)的參數(shù)沒有用括號括起來,但當我們調(diào)用它時,我們會在 lambda 函數(shù)的整個構造以及我們傳遞給它的參數(shù)周圍添加括號
上面代碼中要注意的另一件事是,使用 lambda 函數(shù),我們可以在創(chuàng)建函數(shù)后立即執(zhí)行該函數(shù)并接收結果。這就是所謂的立即調(diào)用函數(shù)執(zhí)行(或 IIFE)
我們可以創(chuàng)建一個帶有多個參數(shù)的 lambda 函數(shù),在這種情況下,我們用逗號分隔函數(shù)定義中的參數(shù)。當我們執(zhí)行這樣一個 lambda 函數(shù)時,我們以相同的順序列出相應的參數(shù),并用逗號分隔它們:
(lambda x, y, z: x + y + z)(3, 8, 1)
Output:
12
也可以使用 lambda 函數(shù)來執(zhí)行條件操作。下面是一個簡單 if-else 函數(shù)的 lambda 模擬:
print((lambda x: x if(x > 10) else 10)(5)) print((lambda x: x if(x > 10) else 10)(12))
Output:
10
12
如果存在多個條件(if-elif-...-else),我們必須嵌套它們:
(lambda x: x * 10 if x > 10 else (x * 5 if x < 5 else x))(11)
Output:
110
但是上面的寫法,又令代碼變得難以閱讀
在這種情況下,具有 if-elif-...-else 條件集的普通函數(shù)將是比 lambda 函數(shù)更好的選擇。實際上,我們可以通過以下方式編寫上面示例中的 lambda 函數(shù):
def check_conditions(x): if x > 10: return x * 10 elif x < 5: return x * 5 else: return x check_conditions(11)
Output:
110
盡管上面的函數(shù)比相應的 lambda 函數(shù)增加了更多行,但它更容易閱讀
我們可以將 lambda 函數(shù)分配給一個變量,然后將該變量作為普通函數(shù)調(diào)用:
increment = lambda x: x + 1 increment(2)
Output:
3
但是根據(jù) Python 代碼的 PEP 8 樣式規(guī)則,這是一種不好的做法
賦值語句的使用消除了 lambda 表達式相對于顯式 def 語句所能提供的唯一好處(即,它可以嵌入到更大的表達式中)
因此如果我們確實需要存儲一個函數(shù)以供進一步使用,我們最好定義一個等效的普通函數(shù),而不是將 lambda 函數(shù)分配給變量
Lambda 函數(shù)在 Python 中的應用
帶有 filter() 函數(shù)的 Lambda
Python 中的 filter() 函數(shù)需要兩個參數(shù):
- 定義過濾條件的函數(shù)
- 函數(shù)在其上運行的可迭代對象
運行該函數(shù),我們得到一個過濾器對象:
lst = [33, 3, 22, 2, 11, 1] filter(lambda x: x > 10, lst)
Output:
<filter at 0x250cb090520>
為了從過濾器對象中獲取一個新的迭代器,并且原始迭代器中的所有項都滿足預定義的條件,我們需要將過濾器對象傳遞給 Python 標準庫的相應函數(shù):list()、tuple()、set ()、frozenset() 或 sorted()(返回排序列表)
讓我們過濾一個數(shù)字列表,只選擇大于 10 的數(shù)字并返回一個按升序排序的列表:
lst = [33, 3, 22, 2, 11, 1] sorted(filter(lambda x: x > 10, lst))
Output:
[11, 22, 33]
我們不必創(chuàng)建與原始對象相同類型的新可迭代對象,此外我們可以將此操作的結果存儲在一個變量中:
lst = [33, 3, 22, 2, 11, 1] tpl = tuple(filter(lambda x: x > 10, lst)) tpl
Output:
(33, 22, 11)
帶有 map() 函數(shù)的 Lambda
我們使用 Python 中的 map() 函數(shù)對可迭代的每個項目執(zhí)行特定操作。它的語法與 filter() 相同:一個要執(zhí)行的函數(shù)和一個該函數(shù)適用的可迭代對象。
map() 函數(shù)返回一個 map 對象,我們可以通過將該對象傳遞給相應的 Python 函數(shù)來從中獲取一個新的迭代:list()、tuple()、set()、frozenset() 或 sorted()
與 filter() 函數(shù)一樣,我們可以從 map 對象中提取與原始類型不同類型的可迭代對象,并將其分配給變量。
下面是使用 map() 函數(shù)將列表中的每個項目乘以 10 并將映射值作為分配給變量 tpl 的元組輸出的示例:
lst = [1, 2, 3, 4, 5] print(map(lambda x: x * 10, lst)) tpl = tuple(map(lambda x: x * 10, lst)) tpl
Output:
<map object at 0x00000250CB0D5F40>
(10, 20, 30, 40, 50)
map() 和 filter() 函數(shù)之間的一個重要區(qū)別是第一個函數(shù)總是返回與原始函數(shù)相同長度的迭代。因此由于 pandas Series 對象也是可迭代的,我們可以在 DataFrame 列上應用 map() 函數(shù)來創(chuàng)建一個新列:
import pandas as pd df = pd.DataFrame({'col1': [1, 2, 3, 4, 5], 'col2': [0, 0, 0, 0, 0]}) print(df) df['col3'] = df['col1'].map(lambda x: x * 10) df
Output:
? col1 ?col2
0 ? ? 1 ? ? 0
1 ? ? 2 ? ? 0
2 ? ? 3 ? ? 0
3 ? ? 4 ? ? 0
4 ? ? 5 ? ? 0
? ?col1 ?col2 ?col3
0 ? ? 1 ? ? 0 ? ?10
1 ? ? 2 ? ? 0 ? ?20
2 ? ? 3 ? ? 0 ? ?30
3 ? ? 4 ? ? 0 ? ?40
4 ? ? 5 ? ? 0 ? ?50
當然要在上述情況下獲得相同的結果,也可以使用 apply() 函數(shù):
df['col3'] = df['col1'].apply(lambda x: x * 10) df
Output:
? ?col1 ?col2 ?col3
0 ? ? 1 ? ? 0 ? ?10
1 ? ? 2 ? ? 0 ? ?20
2 ? ? 3 ? ? 0 ? ?30
3 ? ? 4 ? ? 0 ? ?40
4 ? ? 5 ? ? 0 ? ?50
我們還可以根據(jù)某些條件為另一列創(chuàng)建一個新的 DataFrame 列,對于下面的代碼,我們可以互換使用 map() 或 apply() 函數(shù):
df['col4'] = df['col3'].map(lambda x: 30 if x < 30 else x) df
Output:
? ?col1 ?col2 ?col3 ?col4
0 ? ? 1 ? ? 0 ? ?10 ? ?30
1 ? ? 2 ? ? 0 ? ?20 ? ?30
2 ? ? 3 ? ? 0 ? ?30 ? ?30
3 ? ? 4 ? ? 0 ? ?40 ? ?40
4 ? ? 5 ? ? 0 ? ?50 ? ?50
帶有 reduce() 函數(shù)的 Lambda
reduce() 函數(shù)與 functools Python 模塊相關,它的工作方式如下:
- 對可迭代對象的前兩項進行操作并保存結果
- 對保存的結果和可迭代的下一項進行操作
- 以這種方式在值對上進行,直到所有項目使用可迭代的
該函數(shù)與前兩個函數(shù)具有相同的兩個參數(shù):一個函數(shù)和一個可迭代對象。但是與前面的函數(shù)不同的是,這個函數(shù)不需要傳遞給任何其他函數(shù),直接返回結果標量值:
from functools import reduce lst = [1, 2, 3, 4, 5] reduce(lambda x, y: x + y, lst)
Output:
15
上面的代碼展示了我們使用 reduce() 函數(shù)計算列表總和時的作用
需要注意的是,reduce() 函數(shù)總是需要一個帶有兩個參數(shù)的 lambda 函數(shù),而且我們必須首先從 functools Python 模塊中導入它
Python 中 Lambda 函數(shù)的優(yōu)缺點
優(yōu)點
- 它是評估單個表達式的理想選擇,應該只評估一次
- 它可以在定義后立即調(diào)用
- 與相應的普通語法相比,它的語法更緊湊
- 它可以作為參數(shù)傳遞給高階函數(shù),例如 filter()、map() 和 reduce()
缺點
- 它不能執(zhí)行多個表達式
- 它很容易變得麻煩,可讀性差,例如當它包括一個 if-elif-...-else 循環(huán)
- 它不能包含任何變量賦值(例如,lambda x: x=0 將拋出一個語法錯誤)
- 我們不能為 lambda 函數(shù)提供文檔字符串
總結
總而言之,我們已經(jīng)詳細討論了在 Python 中定義和使用 lambda 函數(shù)的許多方面:
- lambda 函數(shù)與普通 Python 函數(shù)有何不同
- Python 中 lambda 函數(shù)的語法和剖析
- 何時使用 lambda 函數(shù)
- lambda 函數(shù)的工作原理
- 如何調(diào)用 lambda 函數(shù)
- 調(diào)用函數(shù)執(zhí)行(IIFE)的定義
- 如何使用 lambda 函數(shù)執(zhí)行條件操作,如何嵌套多個條件,以及為什么我們應該避免它
- 為什么我們應該避免將 lambda 函數(shù)分配給變量
- 如何將 lambda 函數(shù)與 filter() 函數(shù)一起使用
- 如何將 lambda 函數(shù)與 map() 函數(shù)一起使用
- 我們?nèi)绾卧?pandas DataFrame 中使用
- 帶有傳遞給它的 lambda 函數(shù)的 map() 函數(shù) - 以及在這種情況下使用的替代功能
- 如何將 lambda 函數(shù)與 reduce() 函數(shù)一起使用
- 在普通 Python 上使用 lambda 函數(shù)的優(yōu)缺點
希望今天的討論可以使 Python 中看似令人生畏的 lambda 函數(shù)概念更清晰、更易于應用。
原文鏈接:https://juejin.cn/post/7132429778069487623
相關推薦
- 2022-09-22 Python 閉包與裝飾器
- 2022-05-12 Kotlin 初始化陷阱。初始化注意事項
- 2022-03-28 python?Pandas中數(shù)據(jù)的合并與分組聚合_python
- 2022-05-13 Django-Cookies && Session
- 2022-01-30 uniapp history路由配置,apache服務器簡單配置(刷新報404解決方法)
- 2022-12-23 Python異常信息的不同展現(xiàn)方法總結_python
- 2022-09-12 python?通過dict(zip)和{}的方式構造字典的方法_python
- 2022-01-17 Selenium-Alert彈出框常用處理辦法
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支