Python實(shí)用教程系列——推導(dǎo)式和Lambda表達(dá)式

上次推文我們一起學(xué)習(xí)了python中的高級函數(shù)——Python實(shí)用教程系列——高階函數(shù)Map、Filter、Reduce。推文中重點(diǎn)介紹了map,filter和reduce中相關(guān)概念,也通過實(shí)例的方式介紹了這些函數(shù)的實(shí)際用法,大家可以好好學(xué)習(xí)一下。

有小伙伴對推導(dǎo)式和Lambda的相關(guān)知識不是很清楚,需要我寫一些容易理解的教程,所以這次推文我們就來聊一聊推導(dǎo)式的相關(guān)知識。

一、推導(dǎo)式定義

推導(dǎo)式 comprehensions(又稱解析式),是 Python 的一種獨(dú)有特性。推導(dǎo)式最主要的特點(diǎn)就是可以從一個數(shù)據(jù)序列構(gòu)建另一個新的數(shù)據(jù)序列。在Python 中目前常用的推導(dǎo)式有列表推導(dǎo)式、字典推導(dǎo)式和集合推導(dǎo)式。

二、列表推導(dǎo)式

列表推導(dǎo)式是我們最常使用的,因?yàn)榱斜硎俏覀冏畛J褂玫模浠镜恼Z法示意如下:

  • [表達(dá)式 for 變量 in 列表]
  • [表達(dá)式 for 變量 in 列表 if 條件]

上述表達(dá)式中”[]”是表示Python中的列表。從基本的語法形式上我們看得出來,變量是我們預(yù)先就存在的列表的值,或者是對存在的列表進(jìn)行條件篩選后的值。

我們來看幾個具體的例子就清晰了:

2.1 第一種語法形式

list_a = range(1,10)
list_b = [each for each in list_a]
print(list_b)

# 輸出 [1, 2, 3, 4, 5, 6, 7, 8, 9]

2.2 第二種語法形式

# 輸出 list_a中的基數(shù)

list_a = range(1,10)
list_b = [each for each in list_a if each % 2 ==1]
print(list_b)
# 輸出 [1, 3, 5, 7, 9]

第二種語法形式生成的結(jié)果與第一種不同的原因在于,第二種語法形式中使用了篩選條件:each % 2 ==1

注意list_b使用了”[]”,這就說明了其為一個列表。有的小伙伴還沒看出來的話,我們使用for將第二種形式進(jìn)行改寫:

list_b = []
list_a = range(1,10)
for each in list_a:
   if each % 2 == 1:
       list_b.append(each)
print(list_b)

輸出結(jié)果為list_a中的奇數(shù)組成的列表,if each % 2 == 1在第二種形式中也完全顯示了,可以看出使用列表推導(dǎo)式可以精簡代碼,閱讀起來更加有Python的風(fēng)格。

這里給大家設(shè)置兩個小題目,大家試著解決:

(1)過濾掉列表

names = ['gongsunli’,’machao’,’Gongben’,’Yuji’]中長度大于或等于4的字符串列表,并將剩下字符的轉(zhuǎn)換成大寫字母,結(jié)果保存為列表。

(2)給定列表A=[a,b,c], B=[d,e,f]],找出A和B中元素可以組成的字符串的所有可能,如ab.

三、字典推導(dǎo)式

學(xué)習(xí)了列表推導(dǎo)式以后,學(xué)習(xí)字典推導(dǎo)式就沒什么困難了,字典推導(dǎo)式語法差不多,只不過我們使用”{}”產(chǎn)生的是字典而已,唯一要注意的就是在字典中有鍵和值兩個關(guān)鍵的屬性,仿似列表推導(dǎo)式,那么其基本的語法可以被寫作這樣:

  • { 鍵:值 for 鍵,值 in 數(shù)據(jù)結(jié)構(gòu)}
  • { 鍵:值 for 鍵 in 數(shù)據(jù)結(jié)構(gòu)1 for 值 in 數(shù)據(jù)結(jié)構(gòu)2 }

同樣我們來看幾個實(shí)際的小例子:

3.1 第一種語法形式

list_c = ['我愛','Python學(xué)堂']
dict_c = {k:v for v,k in enumerate(list_c)}
print(dict_c)
# 輸出:{'我愛': 0, 'Python學(xué)堂': 1}

3.2 第二種語法形式

list_a = ['我愛']
list_b = ['Python學(xué)堂']
dict_a = {key: value for key in list_a for value in list_b}
print(dict_a)
#輸出:{'我愛': 'Python學(xué)堂'}

上述代碼塊1中使用了Python的內(nèi)置函數(shù)enumerate()。有基礎(chǔ)的小伙伴一看就知道,enumerate()可將一個可遍歷的數(shù)據(jù)對象(如列表、元組或字符串)組合為一個索引序列,同時列出數(shù)據(jù)下標(biāo)和數(shù)據(jù)。代碼塊2的最后生成的結(jié)果是一個字典(或常使用生成Json數(shù)據(jù)),第二種的字典推導(dǎo)式是非常常見的,大家要掌握好。

再看一個例子:

# 遍歷一個有鍵值關(guān)系的可迭代對象
pro_city = [('江蘇', '南京'), ('福建', '福州'), ('北京', '北京')]
dict_d = {key: value for key, value in pro_city}
print(dict_d)

# {'江蘇': '南京', '福建': '福州', '北京': '北京'}

再如:

dict_e = {key: key * key for key in [1,2,3]}
print(dict_e)

基本上字典推導(dǎo)式就這些,只不過在平時的使用中我們使用一些其他的技巧就能產(chǎn)生一些奇妙的現(xiàn)象。

四、集合推導(dǎo)式

集合我們都很了解,就是一個沒有重復(fù)元素的匯集,跟列表和字典推導(dǎo)式類似,其基本的語法形式可以表示為:

  • { 表達(dá)式for 項(xiàng)in 序列if 條件}

我們先看看集合“{}”,因?yàn)槠涫遣恢貜?fù)的,因此如果有語句:print({1,2,3,4,4,5})會輸出:1,2,3,4,5,重復(fù)的4將會被刪除。

接著我們來看集合的相關(guān)例子:

# 遍歷一個有鍵值關(guān)系的可迭代對象
string_var = '我愛Python學(xué)堂'
res = {value for value in string_var}
print(res)

#輸出為{'h', 'y', 'o', 'P', '我', '愛', '學(xué)', 'n', '堂', 't'}

由于集合是無序性的,因此我們再次運(yùn)行上述代碼的時候,會得到不同的結(jié)果的,比如我們可能得到:

{'我', 'y', 'o', 't', 'h', 'n', '學(xué)', '愛', 'P', '堂'},

{'我', 't', 'o', 'y', 'n', '堂', 'h', '愛', '學(xué)', 'P'}等等。

以上就是推導(dǎo)式相關(guān)的內(nèi)容了,我們再來看一個很好玩的東西,很酷炫的表達(dá)式:lambda表達(dá)式。

五、Lambda表達(dá)式

在Java 和Python中均提供了一個Lambda表達(dá)式,這個表達(dá)式又被稱為匿名函數(shù),是現(xiàn)代各種編程語言爭相引入的一種語法,它設(shè)計精巧,在很大程度上可以精簡代碼,就像推導(dǎo)式一樣。

我們之前的推文講述了map、reduce、filter等函數(shù)都支持函數(shù)作為參數(shù),而Lambda函數(shù)就可以應(yīng)用在函數(shù)式編程中。其基本語法可以簡述如下:

  • Lambda [參數(shù)1[參數(shù)2, … 參數(shù)n]]: 表達(dá)式

參數(shù)的數(shù)量是不固定的,可選的。

我們來看看這個函數(shù)和我們自定義的函數(shù)之間有什么差異,假設(shè)我們現(xiàn)在計算兩個數(shù)的和:

5.1 自定義方式

def add_two(x,y):
   return x + y
print(add_two(1,2))

5.2 Lambda方式

res = lambda x,y:x+y
print(res(1,2))

他們的差別很明顯:Lambda能夠出現(xiàn)在Python語法不允許def出現(xiàn)的地方,def定義的函數(shù)一般用來處理比較復(fù)雜的功能,而Lambda用來處理一些簡單的操作。

之前的推文中,我們講述了一些map、reduce、filter函數(shù),如果這些函數(shù)和Lambda結(jié)合起來使用就會產(chǎn)生一些比較高級的操作,比如:

5.3 與map結(jié)合

list_1=[1,2,3]
list_2=[10,20,30]
print(list(map(lambda x,y:x+y,list_1,list_2)))

#輸出 [11, 22, 33]

5.4 與reduce結(jié)合

from functools import reduce
print(reduce(lambda a,b: a+b ,[1,2,3,4])) # 輸出10

5.5 與filter結(jié)合

num_list = [1,2,3,3,4,5,6,7,8,9,10]
print(list(filter(lambda  x : x % 2 == 0, num_list)))
# 輸出 [2, 4, 6, 8, 10]

實(shí)際使用的中,我們可能會遇道更加復(fù)雜的操作,但是沒關(guān)系,只要理解好lambda的精髓這些問題就不是問題啦!

最后總結(jié)一下使用Lambda的好處:

(1)使用 Lambda 表達(dá)式可省去定義函數(shù)的過程,讓代碼更加簡潔。

(2)Lambda 表達(dá)式具有使用后即釋放的特點(diǎn),從這個角度上提升了程序的性能(如內(nèi)存使用)。

六、總結(jié)

本次推文我們講述了Python中的推導(dǎo)式和Lambda表達(dá)式,這些表達(dá)式能很好精簡代碼并且使得代碼更加的具又Python風(fēng)格,實(shí)際項(xiàng)目中我們可使用它們很好解決問題,比如:leetcode中的第937題《重新排列日志》,有興趣的小伙伴可以研究一下。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容