Python匿名函數Lambda

一、概念介紹

1.匿名函數介紹

在Python中,通過lambda關鍵字來定義的函數稱為匿名函數;
lambda函數能接收任何數量(可以是0個)的參數,但只能返回一個表達式的值,lambda函數是一個函數對象,直接賦值給一個變量,這個變量就成了一個函數對象
語法:lambda 參數 : 表達式
先寫lambda關鍵字,然后依次寫匿名函數的參數,多個參數中間用英文逗號分隔,然后是一個英文冒號,冒號后面寫返回的表達式;

2.匿名函數與普通函數的對比

def sum_func(a, b, c):
    return a + b + c

sum_lambda = lambda a, b, c: a + b + c

print(sum_func(1, 100, 10000))
print(sum_lambda(1, 100, 10000))

運行結果:

10101
10101
  • 可以看到,lambda適用于多個參數、一個返回值的情況,可以用一個變量來接收,變量是一個函數對象,執行這個函數對象的結果與執行一個普通函數的結果一樣。

  • lambda函數比普通函數更簡潔,且沒有聲明函數名,上面的代碼是用一個變量來接收lambda函數返回的函數對象,并不是lambda函數的名字。

3.匿名函數的多種形式

#無參數
lambda_a = lambda :1001
print(lambda_a())

#一個參數
lambda_b = lambda b : b * 10
print(lambda_b(10))

#多個參數
lambda_c = lambda a,b,c : a+b+c
print(lambda_c(5,6,7))

#表達式
lambda_d = lambda x: x if x % 2 ==0 else x+1
print(lambda_d(5))
print(lambda_d(6))

運行結果:

1001
100
18
6
6

lambda的參數可以是0個或多個,并且返回的表達式可以是一個復雜的表達式,只要最后返回的是一個值就可以了;

4.lambda作為一個參數傳遞

def sub_func(a,b,func):
    print('a = ',a)
    print('b = ',b)
    print('a + b = ',func(a,b))

sub_func(12,5,lambda a,b:a+b)

運行結果:

a =  12
b =  5
a + b =  17

5.lambda函數與python內置函數配合使用

list1 = [{'a': 10, 'b': 20}, {'a': 13, 'b': 2}, {'a': 23, 'b': 13}, {'a': 32, 'b': 17}]
max_a = max(list1, key=lambda x: x['a'])		# 列表元素中關鍵字'a'的最大值
max_b = max(list1, key=lambda x: x['b'])		# 列表元素中關鍵字'b'的最大值

print('列表最大數:', max_a)
print('列表最大數:', max_b)

運行結果:

列表最大數: {'a': 32, 'b': 17}
列表最大數: {'a': 10, 'b': 20}

6.lambda作為函數的返回值

def ret_func(a,b):
    return lambda c : a + b + c
return_func = ret_func(50, 51)
print(return_func)
print(return_func(4))

運行結果:

<function ret_func.<locals>.<lambda> at 0x000001711D2B8400>
105

匿名函數可以作為一個函數的返回值,在如上代碼中,ret_func返回的是一個匿名函數,返回的是一個函數對象,當執行這個函數時,可以得到lamdba函數的結果。
注意:其中a,b兩個參數是ret_func中的參數,但執行返回的函數return_func時,已經不在ret_func的作用域內,而lambda函數仍然能使用a,b,參數,說明lambda函數會將它的運行環境保存一份,一直保留到它自己執行的時候使用。

7.匿名函數的優點

  • 使用Python寫一些腳本時,使用lambda可以省去定義函數的過程,讓代碼更精簡;
  • 對于一些抽象的,不會被別的地方再重復使用的函數,有時候函數起個名稱也是個難題,使用lambda不需要考慮命命名問題;
  • 使用lambda在某些時候代碼更容易理解

二、使用場景

使用場景:
1.需要將一個函數對象作為參數來傳遞時,可以直接定義一個lambda函數(作為函數的參數或返回值);
2.要處理的業務符合lambda函數的情況(任意多個參數和一個返回值),并且只有一個地方會使用這個函數,不會在其他地方重用,可以使用lambad函數;
3.與一些python的內置函數配合合適,提高代碼的可讀性;

1、和map函數一起使用

map()函數接收兩個參數,一個是函數,一個是Iterable,map將傳入的函數依次作用到序列的每個元素,并把結果作為新的Iterator返回

遍歷序列,對序列中每個元素進行函數操作,最終獲取新的序列

案例如下:

求列表[1,2,3,4,5,6,7,8,9],返回一個n*n 的列表

#一般解決方案
li = [1,2,3,4,5,6,7,8,9]
for ind,val in enumerate(li):
    li[ind] = val * val
print(li)

[1, 4, 9, 16, 25, 36, 49, 64, 81]

$\textcolor{blue}{enumerate()是python的內置函數, 在字典賞識枚舉、列舉的意思;}$
$\textcolor{blue}{enumerate參數為可遍歷/可迭代的對象(如列表、字符串);}$
$\textcolor{blue}{enumerate多用于在for循環中得到計數,利用它可以同時獲得索引和值,即需要 index 和 value 值的時候可以使用enumerate;}$
$\textcolor{blue}{enumerate()返回的是一個enumerate對象 。}$

#高級解決方案
li = [1,2,3,4,5,6,7,8,9]
print(list(map(lambda x:x*x,li)))

[1, 4, 9, 16, 25, 36, 49, 64, 81]

2、與reduce函數一起使用

reduce把一個函數作用在一個序列[x1, x2, x3, ...]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算,其效果就是:

reduce(func,[1,2,3]) 等同于 func(func(1,2),3),返回值為單個值

對于序列內所有元素進行累計操作

#接受一個list并利用reduce()求積
from functools import reduce
li = [1,2,3,4,5,6,7,8,9]
print(reduce(lambda x,y:x * y,li))

結果 : 123456789 = 362880

a = [12, 34, 56]

print reduce(lambda x , y: x + y, a)  # 102

print reduce(lambda x , y: x - y, a) # -78

3、和filter函數一起使用

filter()也接收一個函數和一個序列。和map()不同的是,filter()把傳入的函數依次作用于每個元素,然后根據返回值是True還是False決定保留還是丟棄該元素。

對于序列中的元素進行篩選,最終獲取符合條件的序列

在一個list中,刪掉偶數,只保留奇數

li = [1, 2, 4, 5, 6, 9, 10, 15]
print(list(filter(lambda x:x % 2==1,li)))  # [1, 5, 9, 15]

回數是指從左向右讀和從右向左讀都是一樣的數,例如12321,909。請利用filter()篩選出回數

li = list(range(1, 200))
print(list(filter(lambda x:int(str(x))==int(str(x)[::-1]),li)))

[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191]

4、和sorted函數一起使用

sorted(iterable, /, *, key=None, reverse=False)

接收一個key函數來實現對可迭代對象進行自定義的排序

可迭代對象:主要與列表,字符串,元祖,集合和字典

key:接受一個函數,根據此函數返回的結果,進行排序

reverse:排序方向,默認為從小到大,reverse=True為逆向

對列表按照絕對值進行排序

li= [-21, -12, 5, 9, 36]
print(sorted(li, key = lambda x:abs(x)))

[5, 9, -12, -21, 36]

"""
sorted()函數按照keys進行排序,并按照對應關系返回list相應的元素:

keys排序結果 => [5, 9, 12, 21, 36]
| | | | |
最終結果 => [5, 9, -12, -21, 36]
"""

把下面單詞以首字母排序

li = ['bad', 'about', 'Zoo', 'Credit']
print(sorted(li, key = lambda x : x[0]))

輸出['Credit', 'Zoo', 'about', 'bad']

"""
對字符串排序,是按照ASCII的大小比較的,由于'Z' < 'a',結果,大寫字母Z會排在小寫字母a的前面。
"""

假設我們用一組tuple表示學生名字和成績:

L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]

請用sorted()對上述列表分別按名字排序

print(sorted(L, key = lambda x : x[0]))

輸出[('Adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88)]

再按成績從高到低排序

print(sorted(L, key = lambda x : x[1], reverse=True))

輸出[('Adam', 92), ('Lisa', 88), ('Bob', 75), ('Bart', 66)]

5、與三元運算結合

如下:

#if 條件為真的時候返回if前面內容,否則返回0 
exp1= lambda x:x+1 if 2==1 else 0 
print(exp1(2))
exp2 = lambda x:x+1 if 1==1 else 0 
print(exp2(2))

輸出:

0
3

#if not 為假返回if not前面內容,否則返回0  
exp3 = lambda x:x+1 if not 2==1 else 0  
print(exp3(2))  

exp4 = lambda x:x+1 if not 1==1 else 0  
print(exp4(2))

輸出:
3
0