python3中apply函數(shù)和lambda函數(shù)的使用詳解
lambda函數(shù)
lambda是什么
大家好,今天給大家?guī)淼氖怯嘘P(guān)于Python里面的lambda表達(dá)式詳細(xì)解析。lambda在Python里面的用處很廣,但說實(shí)話,我個(gè)人認(rèn)為有關(guān)于lambda的討論不是如何使用的問題,而是該不該用的問題。接下來還是通過大量實(shí)例和大家分享我的學(xué)習(xí)體驗(yàn),可能最后你也會(huì)得出和我一樣的結(jié)論。
好啦,首先讓我們先搞明白基礎(chǔ)定義,lambda到底是什么?
Lambda表達(dá)了Python中用于創(chuàng)建匿名函數(shù)的特殊語法。我們將lambda語法本身稱為lambda表達(dá)式,從這里得到的函數(shù)稱之為lambda函數(shù)。
其實(shí)總結(jié)起來,lambda可以理解為一個(gè)小的匿名函數(shù),lambda函數(shù)可以使用任意數(shù)量的參數(shù),但只能有一個(gè)表達(dá)式。估計(jì)有JavaScript ES6經(jīng)驗(yàn)的朋友們聽上去會(huì)很親切,具體函數(shù)表達(dá)式如下:
模板: lambda argument: manipulate(argument)
參數(shù):argument就是這個(gè)匿名函數(shù)傳入的參數(shù),冒號(hào)后面是我們對(duì)這個(gè)參數(shù)的操作方法
讓我們參考上面的定義模板和參數(shù), 直接看一個(gè)最簡(jiǎn)單的例子:
add_one = lambda x:x+1 # 1個(gè)參數(shù),執(zhí)行操作為+1 add_nums = lambda x,y:x+y # 2個(gè)參數(shù),執(zhí)行操作為相加 print(add_one(2)) # 調(diào)用add_one print(add_nums(3,7)) # 調(diào)用add_nums >>> 3 10
相比大家已經(jīng)發(fā)現(xiàn)lambda匿名函數(shù)的特點(diǎn)了,就是對(duì)于較為簡(jiǎn)單的功能,無需自己def一個(gè)了,單行就可以寫下,傳參和執(zhí)行方法一氣呵成
lambda用法詳解
接下來讓我們看看lambda的實(shí)際應(yīng)用,就我自己使用lambda的體驗(yàn)來說,從來沒有單獨(dú)用過,lambda一般情況下是和map,filter,reduce這些超棒的內(nèi)置函數(shù)以及dict,list,tuple,set 等數(shù)據(jù)結(jié)構(gòu)混用,這樣才能發(fā)揮它的最大效果.
好了,閑話少說,下面讓我們一個(gè)個(gè)來看
lambda + map
首先出場(chǎng)的是lambda+map的組合,先看下面這個(gè)例子:
numbers = [1,2,3,4,5] add_one = list(map(lambda n:n+1,numbers)) #map(fun,sequence) print(list(add_one)) print(tuple(add_one)) Out: [2, 3, 4, 5, 6] (2, 3, 4, 5, 6)
這個(gè)是我們上一期的例子,實(shí)現(xiàn)一個(gè)數(shù)組(元組)每個(gè)元素+1,讓我們回憶一下map的用法map(fun,sequence)
,fun是傳遞的方法,sequence是一個(gè)可迭代的序列,這里我們的fun就是匿名函數(shù)lambda n:n+1
,這里非常完美的解釋了lambda的設(shè)計(jì)初衷,因?yàn)槿绻麤]有l(wèi)ambda,我們的解決方案是這樣:
def add(num): return num+1 numbers = [1,2,3,4,5] add_one = list(map(add,numbers)) print(add_one) print(tuple(add_one))
顯然易見,這里的add方法有點(diǎn)多余,所以用lambda代替是個(gè)好的選擇。讓我們?cè)倏聪乱粋€(gè)例子,這是我自己備份日志時(shí)寫的一小段代碼,命名不是很規(guī)范:
from datetime import datetime as dt logs = ['serverLog','appLog','paymentLog'] format ='_{}.py'.format(dt.now().strftime('%d-%m-%y')) result =list(map(lambda x:x+format,logs)) # 利用map+lambda 實(shí)現(xiàn)字符串拼接 print(result) Out:['serverLog_11-02-19.py', 'appLog_11-02-19.py', 'paymentLog_11-02-19.py']
這里和剛才的加1例子差不多,但是換成了字符串的拼接,然而我這里用lambda并不是很好的解決方案,最后我們會(huì)說,現(xiàn)在大家應(yīng)該對(duì)map + lambda 有一些感覺了,讓我們?cè)賮韨€(gè)和dict字典互動(dòng)的例子:
person =[{'name':'Lilei', 'city':'beijing'}, {'name':'HanMeiMei', 'city':'shanghai'}] names=list(map(lambda x:x['name'],person)) print(names) Out:['Lilei', 'HanMeiMei']
好了,看到這里對(duì)于map+lambda的用法大家已經(jīng)很清楚了應(yīng)該~
lambda + filter
lambda和filter的組合也很常見,用于特定篩選條件下,現(xiàn)在讓我們來看上篇文章filter的例子,就應(yīng)該很好理解了:
numbers = [0, 1, 2, -3, 5, -8, 13] # 提取奇數(shù) result = filter(lambda x: x % 2, numbers) print("Odd Numbers are :",list(result)) # 提取偶數(shù) result = filter(lambda x: x % 2 == 0, numbers) print("Even Numbers are :",list(result)) #提取正數(shù) result = filter(lambda x: x>0, numbers) print("Positive Numbers are :",list(result)) Out:Odd Numbers are : [1, -3, 5, 13] Even Numbers are : [0, 2, -8] Positive Numbers are : [1, 2, 5, 13]
這里無非就是我們把filter(fun,sequence)里面的fun換成了我們的lambda,只是lambda的函數(shù)部分(x%2,x%2==0,x>0)都是可以返回True或者False來判斷的,符合fiter的要求,用剛才李雷和韓梅梅的例子也是一個(gè)道理:
person =[{'name':'Lilei', 'city':'beijing'}, {'name':'HanMeiMei', 'city':'shanghai'}] names=list(filter(lambda x:x['name']=='Lilei',person)) # 提取李雷的信息 print(names) Out:[{'name': 'Lilei', 'city': 'beijing'}]
lambda + reduce
還是讓我們看一下上篇文章的例子:
from functools import reduce # Only Python 3 numbers = [1,2,3,4] result_multiply = reduce((lambda x, y: x * y), numbers) result_add = reduce((lambda x,y: x+y), numbers) print(result_multiply) print(result_add) Out:24 10
這個(gè)例子用lambda和reduce的配合實(shí)現(xiàn)了list求累積和和累積乘法。
有意思的是這個(gè)例子具有兩面性,一方面展示了lambda和reduce如何一起使用,另一方面也引出了接下來我想說的重點(diǎn):lambda真的值得用嗎?到底應(yīng)該怎么用?
避免過度使用lambda
通過上面的例子大家已經(jīng)看到了lambda的實(shí)際應(yīng)用場(chǎng)景,但是這里我想和大家分享一下我的看法:我認(rèn)為lambda的缺點(diǎn)略多于優(yōu)點(diǎn),應(yīng)該避免過度使用lambda.
首先,這僅僅是我的個(gè)人看法哈,希望大家理解,我為什么這么說呢,首先讓我們拿lambda方法和常規(guī)def做個(gè)對(duì)比,我發(fā)現(xiàn)lambda和def的主要不同點(diǎn)如下:
- 可以立即傳遞(無需變量)
- 只需一行代碼,簡(jiǎn)潔(未必高效)
- 可以會(huì)自動(dòng)返回,無需return
- lambda函數(shù)沒有函數(shù)名稱
有關(guān)優(yōu)點(diǎn)大家都可以看到,我主要想說一下它的缺點(diǎn),首先,從真正需求出發(fā),我們?cè)诖蠖鄶?shù)時(shí)候是不需要lambda的,因?yàn)榭偪梢哉业礁玫奶娲椒?,現(xiàn)在我們一起看一下剛才lambda+reduce 的例子,我們用lambada實(shí)現(xiàn)的結(jié)果如下:
from functools import reduce # Only Python 3 numbers = [1,2,3,4] result_multiply = reduce((lambda x, y: x * y), numbers) result_add = reduce((lambda x,y: x+y), numbers)
這里用lambda并沒有實(shí)現(xiàn)簡(jiǎn)單高效的目的,因?yàn)槲覀冇鞋F(xiàn)成的sum和mul方法可以用:
from functools import reduce from operator import mul numbers = [1,2,3,4] result_add = sum(numbers) result_multiply =reduce(mul,numbers) print(result_add) print(result_multiply) Out: 10 24
結(jié)果是一樣的,但是顯然用sum和mul的方案更加高效。再舉個(gè)常見的例子說明,假如我們有一個(gè)list存儲(chǔ)了各種顏色,現(xiàn)在要求把每個(gè)顏色首字母大寫,如果用lambda寫出是這樣:
colors = ['red','purple','green','blue'] result = map(lambda c:c.capitalize(),colors) print(list(result)) Out:['Red', 'Purple', 'Green', 'Blue'] 看著似乎不錯(cuò),挺簡(jiǎn)潔的,但是我們有更好的方法: colors = ['red','purple','green','blue'] result = [c.capitalize() for c in colors] print(result) Out:['Red', 'Purple', 'Green', 'Blue'] 用sorted還能處理首字母不規(guī)范的情況,連排序都省了: colors = ['Red','purple','Green','blue'] print(sorted(colors,key=str.capitalize)) Out:['blue', 'Green', 'purple', 'Red']
還有一個(gè)主要原因就是: lambda函數(shù)沒有函數(shù)名稱。所以在代碼交接,項(xiàng)目移植的場(chǎng)景中會(huì)給團(tuán)隊(duì)帶來很多困難,多寫個(gè)函數(shù)add_one()沒什么壞處,因?yàn)榇蠹叶己苋菀桌斫?,知道它是?zhí)行+1的功能,但是如果團(tuán)隊(duì)里你在自己負(fù)責(zé)的模塊使用了很多l(xiāng)ambda,會(huì)給其他人理解帶來很多麻煩
適合lambda的場(chǎng)景
話又說回來,存在即合理,那么真正需要我們使用lambda的是哪些場(chǎng)景呢:
- 你需要的方法是很簡(jiǎn)單的(+1,字符串拼接等),該函數(shù)不值得擁有一個(gè)名字
- 使用lambda表達(dá)式,會(huì)比我們能想到的函數(shù)名稱更容易理解
- 除了lambda,沒有任何python提供的函數(shù)可以實(shí)現(xiàn)目的
- 團(tuán)隊(duì)中所有成員都掌握lambda,大家同意你用
還有一種場(chǎng)景非常適用,就是在給其他人制造自己很專業(yè)的錯(cuò)覺時(shí),比如:
哎呀,小老弟,聽說你學(xué)了Python,知道lambda不? 沒聽過?不行啊,白學(xué)了!
來來來,讓我給你講講。。。此處省略1萬字
總結(jié)
今天為大家九淺一深地講解了lambda的用法和使用場(chǎng)景,所謂九淺一深,就是90%情況下用于創(chuàng)建簡(jiǎn)單的匿名函數(shù),10%的情況稍微復(fù)雜(我這個(gè)借口找的太好了)
總而言之就是,任何事情都具有兩面性,我們?cè)谑褂胠ambda之前應(yīng)該先停下來,問問自己是不是真的需要它。
當(dāng)然,如果需要和別人忽悠的時(shí)候都是正反一張嘴,lambda是好是壞全看我們自己怎么說,吹牛時(shí)請(qǐng)遵守如下原則,屢試不爽:
如果你說一個(gè)女大學(xué)生晚上賣淫就是可恥,但如果改成一個(gè)妓女利用業(yè)余時(shí)間努力學(xué)習(xí)就勵(lì)志多了!
lambda也是如此
apply函數(shù)
Python中apply函數(shù)的格式為:apply(func,*args,**kwargs)
當(dāng)然,func可以是匿名函數(shù)。
用途:當(dāng)一個(gè)函數(shù)的參數(shù)存在于一個(gè)元組或者一個(gè)字典中時(shí),用來間接的調(diào)用這個(gè)函數(shù),并將元組或者字典中的參數(shù)按照順序傳遞給參數(shù)
解析:args
是一個(gè)包含按照函數(shù)所需參數(shù)傳遞的位置參數(shù)的一個(gè)元組,簡(jiǎn)單來說,假如A函數(shù)的函數(shù)位置為 A(a=1,b=2),那么這個(gè)元組中就必須嚴(yán)格按照這個(gè)參數(shù)的位置順序進(jìn)行傳遞(a=3,b=4),而不能是(b=4,a=3)這樣的順序。kwargs
是一個(gè)包含關(guān)鍵字參數(shù)的字典,而其中args如果不傳遞,kwargs需要傳遞,則必須在args的位置留空。
apply的返回值就是函數(shù)func函數(shù)的返回值。
?舉例
def function(a,b): print(a,b) apply(function,('good','better')) apply(function,(2,3+6)) apply(function,('cai','quan')) apply(function,('cai',),{'b':'caiquan'}) apply(function,(),{'a':'caiquan','b':'Tom'})
輸出結(jié)果:
('good', 'better')
(2, 9)
('cai', 'quan')
('cai', 'caiquan')
('caiquan', 'Tom')
對(duì)數(shù)據(jù)進(jìn)行預(yù)處理時(shí),大家使用比較多的是apply函數(shù),apply函數(shù)是pandas庫中的函數(shù),非常好用的一個(gè)函數(shù)相當(dāng)于循環(huán)遍歷,起到對(duì)每一條數(shù)據(jù)進(jìn)行處理的效果,函數(shù)的參數(shù)可能是DataFrame中的行或者列。
說到apply又不得不說lambda函數(shù)了,這兩個(gè)結(jié)合來用簡(jiǎn)直爽的不行。
lambda關(guān)鍵字可以用來創(chuàng)建一個(gè)小的匿名函數(shù)
示例:
DataFrame.apply(func, axis=0, broadcast=False, raw=False, reduce=None, args=(), *kwds)
第一個(gè)參數(shù)func是一個(gè)函數(shù),需要自己實(shí)現(xiàn),可以使用lambda匿名函數(shù),axis默認(rèn)值為0,axis為0時(shí),會(huì)把一列的數(shù)據(jù)進(jìn)行遍歷。
data[‘cut_review'].apply(lambda x: [i for i in x s if i not in stopwords])
?下面的例子是DataFrame中apply的用法
#函數(shù)應(yīng)用和映射 import numpy as np import pandas as pd df=pd.DataFrame(np.random.randn(4,3),columns=list('bde'),index=['utah','ohio','texas','oregon']) print(df) """ b d e utah -0.667969 1.974801 0.738890 ohio -0.896774 -0.790914 0.474183 texas 0.043476 0.890176 -0.662676 oregon 0.701109 -2.238288 -0.154442 """ #將函數(shù)應(yīng)用到由各列或行形成的一維數(shù)組上。DataFrame的apply方法可以實(shí)現(xiàn)此功能 f=lambda x:x.max()-x.min() #默認(rèn)情況下會(huì)以列為單位,分別對(duì)列應(yīng)用函數(shù) t1=df.apply(f) print(t1) t2=df.apply(f,axis=1) print(t2) """ b 1.597883 d 4.213089 e 1.401566 dtype: float64 utah 2.642770 ohio 1.370957 texas 1.552852 oregon 2.939397 dtype: float64 """ #除標(biāo)量外,傳遞給apply的函數(shù)還可以返回由多個(gè)值組成的Series def f(x): return pd.Series([x.min(),x.max()],index=['min','max']) t3=df.apply(f) #從運(yùn)行的結(jié)果可以看出,按列調(diào)用的順序,調(diào)用函數(shù)運(yùn)行的結(jié)果在右邊依次追加 print(t3) """ b d e min -0.896774 -2.238288 -0.662676 max 0.701109 1.974801 0.738890 """ #元素級(jí)的python函數(shù),將函數(shù)應(yīng)用到每一個(gè)元素 #將DataFrame中的各個(gè)浮點(diǎn)值保留兩位小數(shù) f=lambda x: '%.2f'%x t3=df.applymap(f) print(t3) """ b d e utah -0.67 1.97 0.74 ohio -0.90 -0.79 0.47 texas 0.04 0.89 -0.66 oregon 0.70 -2.24 -0.15 """ #注意,之所以這里用map,是因?yàn)镾eries有一個(gè)元素級(jí)函數(shù)的map方法。而dataframe只有applymap。 t4=df['e'].map(f) print(t4) """ utah 0.74 ohio 0.47 texas -0.66 oregon -0.15 """
到此這篇關(guān)于python3中apply函數(shù)和lambda函數(shù)的使用詳解的文章就介紹到這了,更多相關(guān)python3 apply函數(shù)和lambda函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
簡(jiǎn)述python&pytorch 隨機(jī)種子的實(shí)現(xiàn)
這篇文章主要介紹了簡(jiǎn)述python&pytorch 隨機(jī)種子的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10python類中super()和__init__()的區(qū)別
這篇文章主要介紹了python類中super()和__init__()的區(qū)別,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2016-10-10Python實(shí)戰(zhàn)之大魚吃小魚游戲的實(shí)現(xiàn)
這篇文章主要介紹了如何利用Python制作一個(gè)經(jīng)典游戲之大魚吃小魚,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Python有一定幫助,需要的可以參考一下2022-04-04Python argparse模塊應(yīng)用實(shí)例解析
這篇文章主要介紹了Python argparse模塊應(yīng)用實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-1130?個(gè)?Python?函數(shù),加速數(shù)據(jù)分析處理速度
這篇文章主要介紹了30?個(gè)?Python?函數(shù),加速數(shù)據(jù)分析處理速度,Pandas?是?Python?中最廣泛使用的數(shù)據(jù)分析和操作庫。它提供了許多功能和方法,可以加快數(shù)據(jù)分析和預(yù)處理步驟,下面我們就一起來看看這些方法吧,需要的小伙伴可以參考一下,希望給你帶來幫助2021-12-12Python實(shí)現(xiàn)操縱控制windows注冊(cè)表的方法分析
這篇文章主要介紹了Python實(shí)現(xiàn)操縱控制windows注冊(cè)表的方法,結(jié)合實(shí)例形式分析了Python使用_winreg模塊以及win32api模塊針對(duì)Windows注冊(cè)表操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-05-05OpenCV實(shí)戰(zhàn)記錄之基于分水嶺算法的圖像分割
在機(jī)器視覺中,有時(shí)需要對(duì)產(chǎn)品進(jìn)行檢測(cè)和計(jì)數(shù),其難點(diǎn)無非是對(duì)于產(chǎn)品的圖像分割,這篇文章主要給大家介紹了關(guān)于OpenCV實(shí)戰(zhàn)記錄之基于分水嶺算法的圖像分割的相關(guān)資料,需要的朋友可以參考下2023-02-02Python異步爬蟲requests和aiohttp中代理IP的使用
本文主要介紹了Python異步爬蟲requests和aiohttp中代理IP的使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03