匿名函數lambda
Python使用lambda關鍵字創造匿名函數。所謂匿名,意即不再使用def語句這樣標準的形式定義一個函數。這種語句的目的是由于性能的原因,在調用時繞過函數的棧分配。其語法是:
lambda [arg1[, arg2, ... argN]]: expression
其中,參數是可選的,如果使用參數的話,參數通常也會在表達式之中出現。
無參數
# 使用def定義函數的方法
def true():return True#等價的lambda表達式
>>> lambda :True
<function <lambda> at 0x0000000001E42518># 保留lambda對象到變量中,以便隨時調用
>>> true = lambda :True
>>> true()
True
一個參數
# 使用def定義的函數
def add( x, y ):return x + y# 使用lambda的表達式
lambda x, y: x + y# lambda也允許有默認值和使用變長參數
lambda x, y = 2: x + y
lambda *z: z# 調用lambda函數
>>> a = lambda x, y: x + y
>>> a( 1, 3 )
4
>>> b = lambda x, y = 2: x + y
>>> b( 1 )
3
>>> b( 1, 3 )
4
>>> c = lambda *z: z
>>> c( 10, 'test')
(10, 'test')
lambda是單個的表達式,不是一個代碼塊 lambda的設計是為了滿足簡單函數的場景,僅能封裝有限的邏輯,有復雜邏輯的情況有def來處理,所以lambda的功能要比def小的多
lambda表達式是可以嵌套的(閉包)
>>> action = (lambda x : (lambda y : x + y))
>>> a = action(10)
>>> a(5)
15
匿名函數的使用
匿名函數通常被用作高階函數(higher-order function,參數為函數的函數)的參數。比如,幾個內置函數:filter(),map(),reduce()。下面我們分別看看這幾個函數的用法及達到相同效果的python另一種特征的用法
filter函數
>>> list = [1, 2, 3]
>>> result = filter(lambda x: x%2==0, list)
>>> result
[2]
>>> result = [x for x in list if x%2==0]
>>> result
[2]
map函數
>>> result = map(lambda x: x*2, list)
>>> result
[2, 4, 6]
>>> result = [x*2 for x in list]
>>> result
[2, 4, 6]
reduce函數
>>> result = reduce(lambda x, y: x+y,list)
>>> result
6
>>> result = sum(list)
>>> result
6
跳轉表(jump table)
lambda的另一種用法是用來編寫跳轉表,也就是行為列表或字典,能按需執行特定的動作。
>>> key = "get"
>>> {"abc":(lambda : 2 + 2),"bcd" : (lambda : 3 + 3), "get" : (lambda : 4 + 4)}
[key]()
8
注意問題:
x = 10
a = lambda y: y + xx = 20
b = lambda y: y + x#猜想一下:a(10) 和 b(10)返回的結果是什么?如果你認為結果是20 和 30,那么就錯了print(a(10)) ##輸出:30print(b(10)) ##輸出:30
lambda
表達式中的x是一個自由變量, 是在運行時綁定值,而不是定義時就綁定,即lambda表達式中的x是執行時的值,這與函數的默認值參數定義是不同的。例如:
x = 15
print(a(10)) ##輸出:25x = 3
print(a(10)) ##輸出:13
如果想讓匿名函數,在定義時就捕獲到參數值,可以將那個參數值定義成默認參數即可,例如:
m = 4
c = lambda n, m = m: m + nprint(c(10)) ##輸出:14m = 2
print(c(10)) ##輸出:14
有時候,可能會不恰當的使用lambda
表達式。 比如,通過在一個循環或列表推導中創建一個lambda
表達式列表,并期望函數能在定義時就記住每次的迭代值。例如:
funcs = [lambda x: x+n for n in range(3)]
for f in funcs:print(f(0))# 2
# 2
# 2
但是實際效果是,n的值為迭代的最后一個值。將參數值設置為默認參數,才能得到想要的效果,修改代碼如下:
funcs = [lambda x, n = n: x+n for n in range(3)]
for f in funcs:print(f(0))# 0
# 1
# 2
?