匯編語(yǔ)言->C語(yǔ)言->Python抽象程..."/>
您好,登錄后才能下訂單哦!
本文實(shí)例講述了Python函數(shù)式編程。分享給大家供大家參考,具體如下:
函數(shù)式編程就是一種抽象程度很高的編程范式,從計(jì)算機(jī)硬件->匯編語(yǔ)言->C語(yǔ)言->Python抽象程度越高、越貼近于計(jì)算,但執(zhí)行效率也越低。純粹的函數(shù)式編程語(yǔ)言編寫的函數(shù)沒(méi)有變量,因此,任意一個(gè)函數(shù),只要輸入是確定的,輸出就是確定的,這種純函數(shù)我們稱之為沒(méi)有副作用。而允許使用變量的程序設(shè)計(jì)語(yǔ)言,由于函數(shù)內(nèi)部的變量狀態(tài)不確定,同樣的輸入,可能得到不同的輸出,因此,這種函數(shù)是有副作用的。函數(shù)式編程的一個(gè)特點(diǎn)就是,允許把函數(shù)本身作為參數(shù)傳入另一個(gè)函數(shù),還允許返回一個(gè)函數(shù)!
Python對(duì)函數(shù)式編程提供部分支持,支持高階函數(shù)(函數(shù)可以作為變量傳入),支持閉包(返回一個(gè)函數(shù)),有限地支持匿名函數(shù)。由于Python允許使用變量,因此,Python不是純函數(shù)式編程語(yǔ)言。
即可以通過(guò)變量名指向函數(shù),函數(shù)通過(guò)變量名作為參數(shù)傳給另一個(gè)函數(shù),并通過(guò)變量名來(lái)使用。例如下面將開方函數(shù)math.sqrt作為參數(shù)傳遞給變量f,變量名f就指向了函數(shù)math.sqrt,再通過(guò)變量f使用該函數(shù)給x、y開方。
import math def add(x, y, f): return f(x) + f(y) # 函數(shù)作為參數(shù)傳遞給f來(lái)調(diào)用 res = add(25, 9, math.sqrt) print(res)
map函數(shù)接收一個(gè)函數(shù) f 和一個(gè) list,并把函數(shù) f 依次作用在 list 的每個(gè)元素上,得到一個(gè)iterators并返回。
def format_name(s): return s[0].upper()+s[1:].lower() #將列表的每個(gè)元素首字母大寫,其他小寫 print(list(map(format_name, ['adam', 'LISA', 'barT']))) #輸出:['Adam', 'Lisa', 'Bart']
filter()根據(jù)判斷函數(shù)f的結(jié)果自動(dòng)過(guò)濾掉不符合條件的元素,以iterators返回剩下的元素
def is_odd(x): return x % 2 == 1 # 過(guò)濾函數(shù),x為奇返回True f_res = filter(is_odd, [1, 4, 6, 7, 9, 12, 17]) print(list(f_res)) # 輸出過(guò)濾后的結(jié)果list:1 7 9 17
sorted()函數(shù)用于對(duì)可迭代的對(duì)象進(jìn)行排序,參數(shù)key=指定排序的關(guān)鍵字,這里可以借助functools.cmp_to_keys()將比較方法映射為自定義的方法。例如實(shí)現(xiàn)了降序排列,比較函數(shù)cmp返回值 -1 代表a 應(yīng)該排在 b 的前面,如果a排在b 的后面返回 1。如果 a、b相等返回 0。
import functools def cmp(a, b): if b < a: return -1 if a < b: return 1 return 0 a = [1, 2, 5, 4] print(sorted(a, key=functools.cmp_to_key(cmp)))
有時(shí)函數(shù)簡(jiǎn)單到只有一個(gè)表達(dá)式時(shí),為了簡(jiǎn)化代碼可以使用匿名函數(shù)來(lái)代替,匿名函數(shù)一般形式為lambda 參數(shù):返回表達(dá)式,例如lambda x:x*x,就是傳入x參數(shù)并返回x的平方。例如在使用map()函數(shù)時(shí)需要傳入一個(gè)函數(shù)用于list的元素,此時(shí)可以使用匿名函數(shù)作為參數(shù)
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9] res = map(lambda x: x * x, lst) # 將匿名函數(shù)作用于lst print(list(res))
函數(shù)的閉包(Closure)是指內(nèi)層函數(shù)引用了外層函數(shù)的變量,然后將內(nèi)層函數(shù)像變量一樣返回的情況。例如函數(shù)calc_prod()接收一個(gè)list,在其內(nèi)部定義一個(gè)函數(shù)multiply,計(jì)算list元素的乘積并將multiply返回。用f接收calc_prod()的返回函數(shù),并在之后調(diào)用該函數(shù)
def calc_prod(lst): def multiply(): res=1 for i in lst: res=res*i return res return multiply # 將函數(shù)返回 f = calc_prod([1, 2, 3, 4]) # 接收返回函數(shù) print(f()) # 調(diào)用返回函數(shù)
注意在函數(shù)閉包時(shí)要確保引用的局部變量在函數(shù)返回后不能變。例如下面的例子,當(dāng)count()函數(shù)返回3個(gè)函數(shù)時(shí),由于f1、f2、f3并沒(méi)有被調(diào)用,所以并未計(jì)算 i*i。當(dāng) f1 被調(diào)用時(shí),這3個(gè)函數(shù)所引用的變量 i 的值已經(jīng)變成了3,所以此時(shí)使用的變量i的值已經(jīng)發(fā)生了改變,三個(gè)函數(shù)的輸出都是9。
def count(): fs = [] for i in range(1, 4): def f(): print(i) # 函數(shù)f1()調(diào)用時(shí)i已經(jīng)變?yōu)? return i*i fs.append(f) return fs f1, f2, f3 = count() print(f1()) # 輸出9而不是1
函數(shù)裝飾器是指在原有函數(shù)的基礎(chǔ)上對(duì)函數(shù)作修改和裝飾操作。其基本思想是,既然函數(shù)可以像變量一樣作為參數(shù)傳入并且返回,那么我們可以將原來(lái)的函數(shù)傳入裝飾器函數(shù),然后增加我們需要的操作,之后在將原函數(shù)返回出來(lái)。
例如下面定義了一個(gè)裝飾器log用于打印函數(shù)名稱,原函數(shù)作為參數(shù)f傳入。在裝飾器中定義新的函數(shù)fn,其中參數(shù)列*args和**kw代表自適應(yīng)參數(shù)個(gè)數(shù),防止不同參數(shù)個(gè)數(shù)的函數(shù)在使用裝飾器時(shí)不匹配。在新函數(shù)fn中輸出原函數(shù)的名稱,之后將原函數(shù)原封不動(dòng)地調(diào)用一遍并返回出去。最后返回新函數(shù)。
在使用裝飾器時(shí),只需要在函數(shù)的定義前加一行@裝飾器名
def log(f): # 定義裝飾器log def fn(*args, **kw): # 定義新函數(shù) print('函數(shù)名: ' + f.__name__) # 打印函數(shù)名 return f(*args, **kw) # 在新函數(shù)中調(diào)用原函數(shù)并返回結(jié)果 return fn # 返回新函數(shù) @log # 為函數(shù)add添加裝飾器 def add(x, y): return x + y print(add(1, 2))
如果希望給裝飾器傳入一個(gè)參數(shù),則需要定義三重嵌套的函數(shù),在最外層增加一層函數(shù)用于接收參數(shù)。例如希望在打印函數(shù)名之前輸出傳入的參數(shù)“DEBUG”
def log(prefix): def log_decorator(f): def wrapper(*args, **kw): print '[%s] %s()...' % (prefix, f.__name__) return f(*args, **kw) return wrapper return log_decorator @log('DEBUG') # 為裝飾器傳入?yún)?shù) def test(): pass test()
由于裝飾器實(shí)際上是創(chuàng)建了新的函數(shù)fn并替代了原函數(shù),所以原函數(shù)的相關(guān)信息例如函數(shù)名會(huì)被覆蓋,可以用@functools.wraps(f)來(lái)復(fù)制原函數(shù)的信息以保留下來(lái)。
import functools def log(f): @functools.wraps(f) def fn(*args, **kw): print 'call...' return f(*args, **kw) return fn
偏函數(shù)可以為函數(shù)填上一個(gè)固定的參數(shù)值,從而生成一個(gè)新的函數(shù)。例如原函數(shù)add需要兩個(gè)參數(shù)x、y,通過(guò)指定y=1得到偏函數(shù)add1,這個(gè)函數(shù)只需要輸入一個(gè)參數(shù)x,從而計(jì)算x+1的值。
import functools def add(x, y): return x + y add1 = functools.partial(add, y=1) print(add2(3)) # 輸出結(jié)果為4
關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python函數(shù)使用技巧總結(jié)》、《Python面向?qū)ο蟪绦蛟O(shè)計(jì)入門與進(jìn)階教程》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python字符串操作技巧匯總》、《Python編碼操作技巧總結(jié)》及《Python入門與進(jìn)階經(jīng)典教程》
希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。