第八章 函數(shù)-3
8.3 lambda函數(shù)
如果一個函數(shù)的函數(shù)體僅有 1 行表達(dá)式,則該函數(shù)就可以用 lambda 表達(dá)式來代替。lambda 表達(dá)式,又稱匿名函數(shù),常用來表示內(nèi)部僅包含 1 行表達(dá)式的函數(shù)。lambda 表達(dá)式的語法格式如下:
name = lambda [list] : 表達(dá)式
其中,定義 lambda 表達(dá)式,必須使用 lambda 關(guān)鍵字;[list] 作為可選參數(shù),等同于定義函數(shù)是指定的參數(shù)列表;name為該表達(dá)式的名稱。該語法格式轉(zhuǎn)換成普通函數(shù)的形式,如下所示:
def name(list):
??? return 表達(dá)式
name(list)
使用普通方法定義此函數(shù),需要 3 行代碼,而使用 lambda 表達(dá)式更簡潔,可讀性好??磦€例子:
squareSum = lambda x,y:x*x+y*y
print(squareSum(1,2))
如果使用函數(shù)方式實(shí)現(xiàn),如下:
def squareSum(x,y):
??? return x*x+y*y
print(squareSum(1,2))
?
lambda函數(shù)用法(這部分難度大,可以不看):
1. 將lambda函數(shù)賦值給一個變量,通過這個變量間接調(diào)用該lambda函數(shù)。例子就是我們上面給出的,當(dāng)然我們還可以再提供一個例子如下:
passtest = lambda score: 1 if score >60 else 0??? #成績是否及格
print(passtest(46))?? #0
print(passtest(86))?? #1
?
2. 將lambda函數(shù)賦值給其他函數(shù),從而將其他函數(shù)用該lambda函數(shù)替換。
import time
# 為了把標(biāo)準(zhǔn)庫time中的函數(shù)sleep的功能屏蔽(Mock),我們可以在程序初始化時調(diào)用:
time.sleep=lambda x: None
# 這樣,在后續(xù)代碼中調(diào)用time庫的sleep函數(shù)將不會執(zhí)行原有的功能。例如:
time.sleep(3)? # 程序不會休眠 3 秒鐘,而是因?yàn)閘ambda輸出為None,所以這里結(jié)果是什么都不做
?
3. 將lambda函數(shù)作為參數(shù)傳遞給其他函數(shù)。典型的用法就是下面我們常見的幾種高階函數(shù)。
①sorted函數(shù)
my_list = [3,5,-4,-1,0,2,-6]
#按照絕對值、降序排序
new_list=sorted(my_list, key=lambda x: abs(x),reverse=True)
print(my_list)??? # [3,5,-4,-1,0,2,-6]
print(new_list)?? # [-6, 5, -4, 3, 2, -1, 0]
補(bǔ)充sort 與 sorted 區(qū)別:
sort 是應(yīng)用在 list 上的方法,sorted 可以對所有可迭代的對象進(jìn)行排序操作。
list 的 sort 方法返回的是對已經(jīng)存在的列表進(jìn)行操作,而內(nèi)建函數(shù) sorted 方法返回的是一個新的 list,而不是在原來的基礎(chǔ)上進(jìn)行的操作。
?
②filter函數(shù)
filter()方法用于根據(jù)一定的條件對給定的列表進(jìn)行過濾。使用示例如下:
my_list = [1,2,3,4,5,6,7,8,9,10]
new_list = list(filter(lambda a: (a % 3 == 0),my_list))
print(new_list)??? # [3, 6, 9]
my_list是一個列表,它作為參數(shù)傳遞給filter函數(shù)。filter函數(shù)使用lambda函數(shù)檢查列表中的值是否滿足整除3的條件,輸出列表中滿足條件的值。
或者也可以按照下面方法實(shí)現(xiàn):
def is3times(n):
??? return n % 3 == 0
newlist = filter(is3times, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(list(newlist))??? # [3, 6, 9]
?
③map函數(shù)
map函數(shù)可以根據(jù)提供的函數(shù)對指定序列做映射,乘風(fēng)破浪的例子來了:
# ===========一般寫法:===========
# 1、計算平方數(shù)
def square(x):
?????? return x ** 2
?
m=map(square, [1,2,3,4,5])?? # 計算列表各個元素的平方
print(list(m))? # 結(jié)果:[1, 4, 9, 16, 25]
?
# ===========匿名函數(shù)寫法:============
# 2、計算平方數(shù),lambda 寫法
m=map(lambda x: x ** 2, [1, 2, 3, 4, 5])
print(list(m))? # 結(jié)果:[1, 4, 9, 16, 25]
?
# 3、提供兩個列表,將其相同索引位置的列表元素進(jìn)行相加
m=map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
print(list(m))? # 結(jié)果:[3, 7, 11, 15, 19]
?
綜上所述,Python中的map()函數(shù)是一個將給定的列表的值依次在所定義的函數(shù)關(guān)系中迭代并返回一個新列表。寫出下列程序運(yùn)行結(jié)果。
my_list = [1,2,3,4,5,6,7,8,9]
new_list = list(map(lambda a:(a % 3!= 0),my_list))
print(new_list)??? #[True, True, False, True, True, False, True, True, False]
?
④reduce函數(shù)
reduce函數(shù)將一個數(shù)據(jù)集合(列表,元組等)中的所有數(shù)據(jù)進(jìn)行下列操作:用傳給 reduce 中的函數(shù) function(有兩個參數(shù))先對集合中的第 1、2 個元素進(jìn)行操作,得到的結(jié)果再與第三個數(shù)據(jù)用 function 函數(shù)運(yùn)算,最后得到一個結(jié)果。參考一個例子:
from functools import reduce
# ===========一般寫法:===========
# 1、兩數(shù)相加
def add(x, y):
??? return x + y
?
r=reduce(add, [1, 3, 5, 7, 9])? # 計算列表元素和:1+3+5+7+9
print(r)??? # 結(jié)果:25
?
"""
===========執(zhí)行步驟解析:===========
調(diào)用 reduce(add, [1, 3, 5, 7, 9])時,reduce函數(shù)將做如下計算:
1???? 先計算頭兩個元素:f(1, 3),結(jié)果為4;
2???? 再把結(jié)果和第3個元素計算:f(4, 5),結(jié)果為9;
3???? 再把結(jié)果和第4個元素計算:f(9, 7),結(jié)果為16;
4???? 再把結(jié)果和第5個元素計算:f(16, 9),結(jié)果為25;
5???? 由于沒有更多的元素了,計算結(jié)束,返回結(jié)果25。
"""
# ===========匿名函數(shù)寫法:===========
# 2、兩數(shù)相加,lambda 寫法
r=reduce(lambda x, y: x + y, [1, 2, 3, 4, 5])
print(r)??? # 結(jié)果:15
?
# 當(dāng)然求和運(yùn)算可以直接用Python內(nèi)建函數(shù)sum(),沒必要動用reduce。
# 3、但是如果要把序列 [1, 3, 5, 7, 9] 變換成整數(shù) 13579,reduce就可以派上用場:
?
def fn(x, y):
??? return x * 10 + y
?
r=reduce(fn, [1, 3, 5, 7, 9])
print(r)??? # 結(jié)果:13579
?
編程練習(xí):
1. 使用不同方法求1+2+3+……+100的和
# 方法1?
# 這個方法如果不能想出來,自己懲罰自己
# doing sit-ups and jumping jacks,100個怎么樣?
# 仰臥起坐和開合跳,又學(xué)了新單詞了??!
s=0
for i in range(1,101):
??? s=s+i
print(s)
?
# 方法2 使用了reduce函數(shù)
from functools import reduce
def add(x,y):
??? return x + y
print (reduce(add, range(1, 101)))
?
# 方法3,就一行代碼呦!
print(sum(range(1,101)))
?
4. 函數(shù)式編程
?
下面這個例子比較難于理解,別急,慢慢來。
?
# 定義一個普通的python函數(shù)并嵌入 Lambda,函數(shù)接收傳入的一個參數(shù) x。
# 然后將此參數(shù)添加到lambda函數(shù)提供的某個未知參數(shù) y 中求和。
def new_func(x):
??? return(lambda y:x + y)
?
# 只要使用new_func(),就會調(diào)用new_func中存在的lambda函數(shù)。
# 每次都可以將不同的值傳遞給參數(shù)。
f1 = new_func(1)????? # x=5,返回 1+y
f2 = new_func(2)????? # x=2,返回 2+y
print(f1(3))????????? # y=3,返回 1+y=4
print(f2(4))????????? # y=4,返回 2+y=6