匿名函數lambda表達式
什么是匿名函數?
匿名函數,顧名思義就是沒有名字的函數,在程序中不用使用 def 進行定義,可以直接使用 lambda 關鍵字編寫簡單的代碼邏輯。lambda 本質上是一個函數對象,可以將其賦值給另一個變量,再由該變量來調用函數,也可以直接使用。
1
2
3
4
5
6
7
8
9
10
11
12
|
#平時,我們是先定義函數,再進行調用 def power(x): return x * * 2 print (power( 2 )) #使用lambda表達式的時候,我們可以這樣操作 power = lambda x : x * * 2 print (power( 2 )) #覺得太麻煩,還可以這樣調用 print (( lambda x: 2 * x)( 8 )) |
lambda表達式的基本格式:lambda 入參 : 表達式
1
2
3
4
|
#入參可以有多個,比如 power = lambda x, n: x * * n print (power( 2 , 3 )) |
lambda 表達式的使用場景
一般適用于創建一些臨時性的,小巧的函數。比如上面的 power函數,我們當然可以使用 def 來定義,但使用 lambda 來創建會顯得很簡潔,尤其是在高階函數的使用中。
定義一個函數,傳入一個list,將list每個元素的值加1
1
2
3
4
|
def add(l = []): return [x + 1 for x in l] print (add([ 1 , 2 , 3 ])) |
上面的函數改成將所有元素的值加2
可能大家會說,這還不簡單,直接把return里的1改成2就行了。但是真的行嗎?如果函數被多個地方使用,而其他地方并不想加2,怎么辦?
這好辦,把變得那部分抽出來,讓調用者自己傳
1
2
3
4
5
6
7
8
9
10
11
|
def add(func,l = []): return [func(x) for x in l] def add1(x): return x + 1 def add2(x): return x + 2 print (add(add1,[ 1 , 2 , 3 ])) print (add(add2,[ 1 , 2 , 3 ])) |
一個簡簡單單的問題,一定要用這么多代碼實現?
1
2
3
4
5
|
def add(func,l = []): return [func(x) for x in l] print (add( lambda x:x + 1 ,[ 1 , 2 , 3 ])) print (add( lambda x:x + 2 ,[ 1 , 2 , 3 ])) |
map函數
map的基本格式
map(func, *iterables)
map() 函數接收兩個以上的參數,開頭一個是函數,剩下的是序列,將傳入的函數依次作用到序列的每個元素,并把結果作為新的序列返回。也就是類似 map(func,[1,2,3])
同樣的,我們還是來完成這樣一個功能:將list每個元素的值加1
1
2
3
4
5
6
|
def add(x): return x + 1 result = map (add, [ 1 , 2 , 3 , 4 ]) print ( type (result)) print ( list (result)) |
使用lambda表達式簡化操作
1
2
3
|
result = map ( lambda x: x + 1 , [ 1 , 2 , 3 , 4 ]) print ( type (result)) print ( list (result)) |
函數中帶兩個參數的map函數格式
使用map函數,將兩個序列的數據對應位置求和,之后返回,也就是對[1,2,3],[4,5,6]兩個序列進行操作之后,返回結果[5,7,9]
1
|
print ( list ( map ( lambda x, y: x + y, [ 1 , 2 , 3 ], [ 4 , 5 , 6 ]))) |
對于兩個序列元素個數一樣的,相對好理解。如果兩個序列個數不一樣的,會不會報錯?
1
|
print ( list ( map ( lambda x, y: x + y, [ 1 , 2 , 3 ], [ 4 , 5 ]))) |
我們可以看到不會報錯,但是結果以個數少的為準
reduce函數
reduce函數的基本格式
reduce(function, sequence, initial=None)
reduce把一個函數作用在一個序列上,這個函數必須接收兩個參數,reduce函數把結果繼續和序列的下一個元素做累積計算,跟遞歸有點類似,reduce函數會被上一個計算結果應用到本次計算中
reduce(func, [1,2,3]) = func(func(1, 2), 3)
使用reduce函數,計算一個列表的乘積
1
2
3
4
5
6
|
from functools import reduce def func(x, y): return x * y print ( reduce (func, [ 1 , 2 , 3 , 4 ])) |
結合lambda表達式,簡化操作
1
2
3
|
from functools import reduce print ( reduce ( lambda x, y: x * y, [ 1 , 2 , 3 , 4 ])) |
filter 函數
filter 顧名思義是過濾的意思,帶有雜質的(非需要的數據),經過 filter 處理之后,就被過濾掉。
filter函數的基本格式
filter(function_or_None, iterable)
filter() 接收一個函數和一個序列。把傳入的函數依次作用于每個元素,然后根據返回值是 True 還是 False 決定保留還是丟棄該元素。
使用 filter 函數對給定序列進行操作,最后返回序列中所有偶數
1
|
print ( list ( filter ( lambda x: x % 2 = = 0 , [ 1 , 2 , 3 , 4 , 5 ]))) |
sorted 函數
sorted從字面上就可以看去這是個用來排序的函數,sorted 可以對所有可迭代的對象進行排序操作
sorted的基本格式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
sorted (iterable, key = None , reverse = False ) #iterable -- 可迭代對象。 #key -- 主要是用來進行比較的元素,只有一個參數,具體的函數的參數就是取自于可迭代對象中,指定可迭代對象中的一個元素來進行排序。 #reverse -- 排序規則,reverse = True 降序 , reverse = False 升序(默認)。 #對序列做升序排序 print ( sorted ([ 1 , 6 , 4 , 5 , 9 ])) #對序列做降序排序 print ( sorted ([ 1 , 6 , 4 , 5 , 9 ], reverse = True )) #對存儲多個列表的列表做排序 data = [[ "Python" , 99 ], [ "c" , 88 ]] print ( sorted (data, key = lambda item: item[ 1 ])) |
閉包
在萬物皆對象的Python中,函數是否能作為函數的返回值進行返回呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
def my_power(): n = 2 def power(x): return x * * n return power p = my_power() print (p( 4 )) #------------------------------------------------------------ def my_power(): n = 2 def power(x): return x * * n return power n = 3 p = my_power() print (p( 4 )) |
我們可以看到,my_power 函數在返回的時候,也將其引用的值(n)一同帶回,n 的值被新的函數所使用,這種情況我們稱之為閉包
當我們把n的值移除到my_power函數外面,這個時候來看下計算結果
1
2
3
4
5
6
7
8
9
10
|
n = 2 def my_power(): def power(x): return x * * n return power n = 3 p = my_power() print (p( 4 )) |
為什么輸出的結果會是64?
我們先來看看閉包時,p.__closure____的結果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#例1 def my_power(): n = 2 def power(x): return x * * n return power p = my_power() print (p.__closure__) #結果:(<cell at 0x00000264518F9A38: int object at 0x00007FFA7F617120>) #closure是內部函數的一個屬性,用來保存環境變量 #--------------------------------------------------------------------- #例2 n = 2 def my_power(): def power(x): return x * * n return power n = 3 p = my_power() print (p.__closure__) #輸出結果 None |
通過例1跟例2對比,我們可以知道,例2并不是閉包
閉包經典問題
下面的程序是否是閉包?能否正確運行
1
2
3
4
5
6
7
8
9
10
11
|
def my_power(): n = 2 def power(x): n + = 1 return x * * n return power p = my_power() print (p( 3 )) |
如何讓上面的程序正確運行?看看改正之后的結果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
def my_power(): n = 2 def power(x): nonlocal n n + = 1 return x * * n return power p = my_power() print (p.__closure__) print (p( 3 )) print (p( 3 )) |
看看下面的程序的運行結果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
def my_power(): n = 2 L = [] for i in range ( 1 , 3 ): def power(): return i * * n L.append(power) return L f1, f2 = my_power() print (f1()) print (f2()) print (f1.__closure__[ 0 ].cell_contents) print (f2.__closure__[ 0 ].cell_contents) |
python的函數只有在執行時,才會去找函數體里的變量的值,也就是說你連形參都不確定,你咋求知道 i為幾呢?在這里,你只需要記住如果你連形參都不確定,python就只會記住最后一個i值。
裝飾器及其應用
什么是裝飾器模式
裝飾器模式(Decorator Pattern)允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬于結構型模式,它是作為現有的類的一個包裝。
這種模式創建了一個裝飾類,用來包裝原有的類,并在保持類方法簽名完整性的前提下,提供了額外的功能。
1
2
3
4
5
6
|
import time start = time.time() time.sleep( 4 ) end = time.time() print (end - start) |
從實際例子來看裝飾器
1
2
3
4
|
def my_fun(): print ( "這是一個函數" ) my_fun() |
要再打印“這是一個函數”前面在打印多一行hello world。
1
2
3
4
5
6
7
8
|
def my_fun(): begin = time.time() time.sleep( 2 ) print ( "這里一個函數" ) end = time.time() print (end - begin) my_fun() |
這個時候,如果不想修改原有的函數,咋整?
1
2
3
4
5
6
7
8
9
10
11
|
def my_fun(): print ( "這是一個函數" ) def my_time(func): begin = time.time() time.sleep( 2 ) func() end = time.time() print (end - begin) my_time(func) |
這種方式,因為要增加功能,導致所有的業務調用方都得進行修改,此法明顯不可取。
另一種方式:
1
2
3
4
5
6
7
8
9
10
11
12
|
def print_cost(func): def wrapper(): begin = time.time() time.sleep( 2 ) func() end = time.time() print (end - begin) return wrapper @print_cost def my_fun(): print ( "這里一個函數" ) |
第二種方式并沒有修改func函數的內部實現,而是使用裝飾器模式對其功能進行裝飾增強。
以上就是淺談Python 函數式編程的詳細內容,更多關于Python 函數式編程的資料請關注服務器之家其它相關文章!
原文鏈接:https://www.cnblogs.com/jwen1994/p/13127205.html