Python基础(六)—函数式编程(内部函数、闭包、lambda、filter/map/reduce/sorce、偏函数)
內部函數
Python中函數的作用域由def關鍵字界定,函數內的代碼訪問變量的方式是從其所在層級由內向外,若往外直至全局作用域都查找不到的話代碼會拋異常。
主要看以下代碼的差別~~
閉包 closure
-
閉包的一些定義
-
閉包的定義:閉包是由函數及其相關的引用環境組合而成的實體(即:閉包=函數+引用環境)。
-
python中閉包的定義:如果在一個內部函數里,對在外部作用域(但不是在全局作用域)的變量進行引用,那么內部函數就被認為是閉包(closure)
-
閉包函數的必要條件:
- 閉包函數必須返回一個函數對象
- 閉包函數返回的那個函數必須引用外部變量(一般不能是全局變量),而返回的那個函數內部不一定要return
- 閉包函數引用的外部變量不一定就是其父函數的參數,也可以是父函數作用域內的任意變量
下面三個例子為常見的閉包
-
-
為何稱作閉包
def line_conf(a):b=1def line(x):return a * x + breturn lineline_A = line_conf(2)b=20print(line_A(1)) # 3
按照命令式語言的規則,ExFunc函數只是返回了內嵌函數InsFunc的地址,在執行InsFunc函數時將會由于在其作用域內找不到sum變量而出 錯。而在函數式語言中,當內嵌函數體內引用到體外的變量時,將會把定義時涉及到的引用環境和函數體打包成一個整體(閉包)返回。
以下列子:- line_A對象作為line_conf返回的閉包對象,它引用了line_conf下的變量b=1,在print時,全局作用域下定義了新的b變量指向20,最終結果仍然引用的line_conf內的b。這是因為,閉包作為對象被返回時,它的引用變量就已經確定(已經保存在它的__closure__屬性中),不會再被修改。
- 即閉包函數被當作變量返回時,它的所有變量就已經固定,形成了一個封閉的對象,這個對象包含了其引用的所有外部、內部變量和表達式。當然,閉包的參數例外。
-
顯式查看閉包
L = line_conf()print(line_conf().__closure__) #(<cell at 0x05BE3530: int object at 0x1DA2D1D0>,for i in line_conf().__closure__: print(i.cell_contents) # 打印引用的外部變量值,為1, 2
__closure__屬性返回的是一個元組對象,包含了閉包引用的外部變量。
根據NO.1,可以使用一些代碼查看閉包信息: -
閉包的作用
#定義兩條直線line_A = line_conf(2, 1) #y=2x+bline_B = line_conf(3, 2) #y=3x+2#打印x對應y的值print(line_A(1)) #3print(line_B(1)) #5# 不使用閉包的代碼def line_A(x):return 2*x+1def line_B(x):return 3*x+2print(line_A(1)) #3print(line_B(1)) #5
閉包最主要的作用是提高代碼的可復用性,根據NO.1,輸出兩條直線:兩條直線看不出區別,當需要定義幾十幾百條,閉包優勢就出來了。
-
閉包的實際運用
-
例子1:
def who(name):def do(what):print(name, 'say:', what)return dolucy = who('lucy')john = who('john')lucy('i want drink!')lucy('i want eat !')lucy('i want play !')john('i want play basketball')john('i want to sleep with U,do U?')lucy("you just like a fool, but i got you!")
-
匿名函數 lambda
- 特性
使用lambda可以精簡代碼、不需要考慮重名函數、可讀性,lambda argument_list: expression,特性如下:- lambda函數是匿名的:所謂匿名函數,通俗地說就是沒有名字的函數。lambda函數沒有名字;
- lambda函數有輸入和輸出:輸入是傳入到參數列表argument_list的值,輸出是根據表達式expression計算得到的值
- lambda函數一般功能簡單:單行expression決定了lambda函數不可能完成復雜的邏輯,只能完成非常簡單的功能。(不支持if else等邏輯判斷)
- 示例:
- lambda x, y: xy;函數輸入是x和y,輸出是它們的積xy
- lambda:None;函數沒有輸入參數,輸出是None
- lambda *args: sum(args); 輸入是任意個數的參數,輸出是它們的和(隱性要求是輸入參數必須能夠進行加法運算)
- lambda **kwargs: 1;輸入是任意鍵值對參數,輸出是1
映射map/reduce
- map
- 功能: 求一個序列或者多個序列進行函數映射之后的值,就該想到map這個函數,它是python自帶的函數,在python3.*之后返回的是迭代器,同filter,需要進行列表轉換
- 調用: map(function,iterable1,iterable2),function中的參數值不一定是一個x,也可以是x和y,甚至多個;后面的iterable表示需要參與function運算中的參數值,有幾個參數值就傳入幾個iterable
- 實例:
- reduce
從python 3 開始移到了 functools 模塊- reduce()函數接收的參數和 map()類似,一個函數 f,一個list,但行為和 map()不同,reduce()傳入的函數 f 必須接收兩個參數,reduce()對list的每個元素反復調用函數f,并返回最終結果值。
- reduce()還可以接收第3個可選參數,作為計算的初始值
過濾器 filter
-
功能: filter的功能是過濾掉序列中不符合函數條件的元素,當序列中要刪減的元素可以用某些函數描述時,就應該想起filter函數。
-
調用: filter(function,sequence),function可以是匿名函數或者自定義函數,它會對后面的sequence序列的每個元素判定是否符合函數條件,返回TRUE或者FALSE,從而只留下TRUE的元素;sequence可以是列表、元組或者字符串
-
實例:
x = [1,2,3,4,5]list(filter(lambda x:x%2==0,x)) # 找出偶數。python3.*之后filter函數返回的不再是列表而是迭代器,所以需要用list轉換。# 輸出:[2, 4]
sorted、sort
- 基本
前面也說有高階函數:map/reduce、filter。sorted()也是一個高階函數。用sorted()排序的關鍵在于實現一個映射函數。
- 默認是升序排序,可用:reverse=True 實現倒敘排序。
- 默認情況下,對字符串排序,是按照ASCII的大小比較的,由于’Z’ < ‘a’,結果,大寫字母Z會排在小寫字母a的前面。可用:key=str.lower 忽略首字母的大小寫。
- sorted和sort
- sort方法是列表類型list的內置方法,使用sort方法對list排序會修改list本身,不會返回新的list,sort方法只能用于列表,不能對字典、元祖等其他可迭代對象進行排序。
list.sort( key=None, reverse=False) - sorted() 函數能對所有可迭代的對象進行排序操作,sorted()函數不會改變原來的對象,而是會返回一個新的已經排序好的對象。
sorted(iterable, key=None, reverse=False)
- sort方法是列表類型list的內置方法,使用sort方法對list排序會修改list本身,不會返回新的list,sort方法只能用于列表,不能對字典、元祖等其他可迭代對象進行排序。
- 排序與lambda
lambda可用實現字典key或者是value的排序,又或者是JSON格式的排序。樣例如代碼:
偏函數
functools模塊提供有wrap與偏函數,可以設定參數的默認值,降低函數的調用難度。
例如,我們有個需求,需要將二進制轉為int,那應該是:
int(‘100000101’, base=2) # 261
每次轉換都這樣,比較麻煩,于是寫了函數int2
使用functools.partial就是幫助創建一個這樣的偏函數,不用自己定義int2()
創建偏函數時,實際上可以接受 函數對象、*args、**kw 這三個參數,以上例子實際上固定了int()函數的關鍵參數base,也就是:
int2(‘101010110’)
相當于:
kw = {‘base’, 2}
int(‘101010110’, **kw)
當傳入:
max2 = functools.partial(max, 10)
實際上會將10作為 *args 的一部分自動加到左邊,也就是:
max2(4, 9) 相當于: max2(10, 4, 9)
偏函數用于固定住原函數的部分參數,使得調用更簡單。
個人博客:Loak 正 - 關注人工智能及互聯網的個人博客
文章地址:Python基礎(六)—函數式編程(內部函數、閉包、lambda、filter/map/reduce/sorce、偏函數)
總結
以上是生活随笔為你收集整理的Python基础(六)—函数式编程(内部函数、闭包、lambda、filter/map/reduce/sorce、偏函数)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电子病历系统源码(EMP) 医院系统源码
- 下一篇: 有关实验室电源远程监控系统的设计与实现