Python函數(shù)式編程的用法詳解
1.純函數(shù)
純函數(shù)是指不產(chǎn)生副作用的函數(shù),即只依賴(lài)于輸入?yún)?shù)并返回輸出結(jié)果,而不修改任何外部狀態(tài)。純函數(shù)通常易于測(cè)試、可組合和并發(fā)執(zhí)行。例如,下面是一個(gè)非純函數(shù):
total = 0 def add(n): global total total += n return total
這個(gè)函數(shù)會(huì)修改total全局變量,因此是有副作用的。相反,下面是一個(gè)純函數(shù):
def add(n): return n + 1
這個(gè)函數(shù)只依賴(lài)于輸入?yún)?shù)并返回輸出結(jié)果,沒(méi)有任何副作用。
2.函數(shù)是一等公民
在函數(shù)式編程中,函數(shù)是一等公民。這意味著函數(shù)可以像其他數(shù)據(jù)類(lèi)型一樣傳遞給其他函數(shù),也可以從其他函數(shù)中返回。例如:
def apply(func, arg): return func(arg) def double(x): return x * 2 print(apply(double, 5)) # 輸出 10
在這個(gè)例子中,我們定義了一個(gè)名為apply
的函數(shù),它接受兩個(gè)參數(shù):一個(gè)函數(shù)和一個(gè)參數(shù)。它將這個(gè)參數(shù)傳遞給這個(gè)函數(shù)并返回結(jié)果。
3.高階函數(shù)
高階函數(shù)是指接受一個(gè)或多個(gè)函數(shù)作為參數(shù)和/或返回一個(gè)函數(shù)的函數(shù)。Python提供了許多內(nèi)置的高階函數(shù),如map
,filter
和reduce
。例如:
# map def square(x): return x ** 2 numbers = [1, 2, 3, 4, 5] squares = list(map(square, numbers)) print(squares) # 輸出 [1, 4, 9, 16, 25] # filter def is_even(x): return x % 2 == 0 numbers = [1, 2, 3, 4, 5] evens = list(filter(is_even, numbers)) print(evens) # 輸出 [2, 4] # reduce from functools import reduce def add(x, y): return x + y numbers = [1, 2, 3, 4, 5] sum = reduce(add, numbers) print(sum) # 輸出 15
在這個(gè)例子中,我們定義了三個(gè)函數(shù):square
,is_even
和add
。然后,我們使用內(nèi)置的高階函數(shù)map
,filter
和reduce
來(lái)對(duì)數(shù)字列表進(jìn)行操作。
4.Lambda表達(dá)式
Lambda表達(dá)式是一種匿名函數(shù),可以用來(lái)定義簡(jiǎn)單的函數(shù)。它們通常在需要一個(gè)函數(shù)作為參數(shù)的地方使用。例如:
numbers = [1, 2, 3, 4, 5] squares = list(map(lambda x: x ** 2, numbers)) print(squares) # 輸出 [1, 4, 9, 16, 25] evens = list(filter(lambda x: x % 2 == 0, numbers)) print(evens) # 輸出 [2, 4]
在這個(gè)例子中,我們使用Lambda表達(dá)式來(lái)定義map
和filter
函數(shù)的函數(shù)參數(shù)。
5.偏函數(shù)
偏函數(shù)是指通過(guò)部分設(shè)置參數(shù)來(lái)創(chuàng)建新函數(shù)的過(guò)程。在Python中,我們可以使用functools.partial函數(shù)來(lái)實(shí)現(xiàn)偏函數(shù)。偏函數(shù)是一種指定部分參數(shù)的函數(shù)。例如,假設(shè)有一個(gè)函數(shù):
def power(base, exponent): return base ** exponent
如果要計(jì)算2
的平方和立方,可以這樣實(shí)現(xiàn):
print(power(2, 2)) print(power(2, 3))
輸出:
4
8
使用偏函數(shù)可以更方便地計(jì)算多個(gè)指數(shù)。例如:
from functools import partial square = partial(power, exponent=2) cube = partial(power, exponent=3) print(square(2)) print(cube(2))
輸出:
4
8
這里使用了functools.partial
函數(shù)將power
函數(shù)的exponent
參數(shù)固定為2
或3
,從而創(chuàng)建了兩個(gè)新的函數(shù)square
和cube
。
6.函數(shù)組合
函數(shù)組合是指將多個(gè)函數(shù)組合成一個(gè)函數(shù)。例如,假設(shè)有兩個(gè)函數(shù):
def add1(n): return n + 1 def double(n): return n * 2
現(xiàn)在要實(shí)現(xiàn)一個(gè)新函數(shù),將add1
和double
組合起來(lái),可以這樣實(shí)現(xiàn):
def compose(f, g): return lambda x: f(g(x)) add1_double = compose(add1, double) print(add1_double(3))
輸出:
7
這個(gè)函數(shù)首先將輸入?yún)?shù)3
傳遞給double
函數(shù),然后將其結(jié)果6
傳遞給add1
函數(shù),最終得到7
。
7.不可變性
函數(shù)式編程鼓勵(lì)不可變性,盡量減少或避免可變狀態(tài)和副作用。這可以通過(guò)使用元組、凍結(jié)集合和不可變對(duì)象來(lái)實(shí)現(xiàn)。例如:
# 元組 person = ('John', 25) name, age = person # 凍結(jié)集合 my_set = frozenset([1, 2, 3]) # 不可變對(duì)象 from collections import namedtuple Person = namedtuple('Person', ['name', 'age']) person = Person(name='John', age=25)
在這個(gè)例子中,我們使用元組、凍結(jié)集合和不可變對(duì)象來(lái)創(chuàng)建不可變數(shù)據(jù)結(jié)構(gòu)。
8. 尾遞歸優(yōu)化
尾遞歸是指函數(shù)的最后一個(gè)操作是它自己的遞歸調(diào)用。這可以通過(guò)迭代實(shí)現(xiàn),并且可以避免堆棧溢出錯(cuò)誤。Python沒(méi)有尾遞歸優(yōu)化,但可以使用生成器和迭代器來(lái)模擬。尾遞歸優(yōu)化是一種技術(shù),它可以將遞歸函數(shù)的調(diào)用棧優(yōu)化為迭代循環(huán),從而減少內(nèi)存占用和提高程序性能。
在 Python 中實(shí)現(xiàn)尾遞歸優(yōu)化有兩種方法:
使用 sys.setrecursionlimit() 函數(shù)增加最大遞歸深度。
實(shí)現(xiàn)一個(gè)尾遞歸函數(shù),并使用一個(gè) while 循環(huán)替換遞歸調(diào)用。
以下是一個(gè)簡(jiǎn)單的例子:
import sys sys.setrecursionlimit(10000) def factorial(n, acc=1): if n == 0: return acc else: return factorial(n-1, acc*n) def tail_recursion_factorial(n, acc=1): while n > 0: n, acc = n-1, acc*n return acc
在這個(gè)例子中,我們定義了兩個(gè)函數(shù):factorial
和 tail_recursion_factorial
。factorial
是一個(gè)正常的遞歸函數(shù),而 tail_recursion_factorial
是一個(gè)尾遞歸函數(shù)。
如果使用 factorial(1000)
這樣的參數(shù)調(diào)用 factorial
函數(shù),將會(huì)產(chǎn)生 RecursionError
,因?yàn)槟J(rèn)情況下 Python
的最大遞歸深度為1000
。為了解決這個(gè)問(wèn)題,我們?cè)黾恿俗畲筮f歸深度并重新運(yùn)行代碼。
使用 tail_recursion_factorial(1000)
來(lái)調(diào)用 tail_recursion_factorial
函數(shù),則不會(huì)出現(xiàn)RecursionError
,因?yàn)樵摵瘮?shù)被優(yōu)化為迭代循環(huán)。
需要注意的是,尾遞歸優(yōu)化并不總是有效,因?yàn)橛袝r(shí)候需要保留函數(shù)調(diào)用棧以便于在返回時(shí)執(zhí)行一些操作。此外,在 Python
中默認(rèn)情況下并沒(méi)有進(jìn)行尾遞歸優(yōu)化,因此需要手動(dòng)實(shí)現(xiàn)它。
9.總結(jié)
Python函數(shù)式編程是一種編程范式,它的核心思想是將計(jì)算視為數(shù)學(xué)函數(shù)的運(yùn)算,并且避免使用可變狀態(tài)和副作用。在這篇教程總結(jié)中,我們將討論如何使用Python進(jìn)行函數(shù)式編程。
第一步是理解函數(shù)是什么。在函數(shù)式編程中,函數(shù)被認(rèn)為是“一等公民”,這意味著它們可以像任何其他數(shù)據(jù)類(lèi)型一樣傳遞和操作。因此,函數(shù)通常會(huì)接受輸入并返回輸出,而不會(huì)修改狀態(tài)或影響外部環(huán)境。
然后,我們需要了解Python中的lambda表達(dá)式。Lambda表達(dá)式是一種匿名函數(shù),它可以在需要時(shí)方便地定義和調(diào)用。它的語(yǔ)法類(lèi)似于“lambda arguments: expression”,其中arguments是參數(shù)列表,expression是函數(shù)體。
接下來(lái)是高階函數(shù)。在函數(shù)式編程中,高階函數(shù)是指接受一個(gè)或多個(gè)函數(shù)作為參數(shù)的函數(shù),或者返回一個(gè)新函數(shù)的函數(shù)。例如,map()函數(shù)可以接受一個(gè)函數(shù)和一個(gè)序列,并返回一個(gè)新序列,其中每個(gè)元素都是通過(guò)應(yīng)用給定函數(shù)得到的結(jié)果。
還有一個(gè)重要的概念是閉包。閉包是指一個(gè)函數(shù)內(nèi)部定義的函數(shù),它可以訪問(wèn)其外部函數(shù)的變量和參數(shù)。這使得我們可以創(chuàng)建一些特殊的函數(shù),例如currying和partial functions。
此外,函數(shù)式編程還涉及到一些常見(jiàn)的函數(shù),例如filter()、reduce()和sorted()。這些函數(shù)可以幫助我們?cè)赑ython中進(jìn)行函數(shù)式編程。
最后,我們需要了解如何避免使用可變狀態(tài)和副作用。這意味著我們應(yīng)該盡可能避免修改對(duì)象的狀態(tài)或影響外部環(huán)境。相反,我們應(yīng)該嘗試編寫(xiě)純函數(shù),這些函數(shù)只依賴(lài)于其輸入,并且不會(huì)修改狀態(tài)或引起副作用。
總之,在Python中進(jìn)行函數(shù)式編程需要掌握l(shuí)ambda表達(dá)式、高階函數(shù)、閉包以及避免使用可變狀態(tài)和副作用等概念。通過(guò)這些技術(shù),我們可以創(chuàng)建更具可讀性、可維護(hù)性和可重用性的代碼。
以上就是Python函數(shù)式編程的用法詳解的詳細(xì)內(nèi)容,更多關(guān)于Python函數(shù)式編程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python如何編寫(xiě)類(lèi)似nmap的掃描工具
這篇文章主要介紹了python如何編寫(xiě)類(lèi)似nmap的掃描工具,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11python實(shí)現(xiàn)簡(jiǎn)易內(nèi)存監(jiān)控
這篇文章主要介紹了python實(shí)現(xiàn)簡(jiǎn)易內(nèi)存監(jiān)控,每隔3秒獲取系統(tǒng)內(nèi)存,當(dāng)內(nèi)存超過(guò)設(shè)定的警報(bào)值時(shí),獲取所有進(jìn)程占用內(nèi)存并發(fā)出警報(bào)聲,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06python3 實(shí)現(xiàn)對(duì)圖片進(jìn)行局部切割的方法
今天小編就為大家分享一篇python3 實(shí)現(xiàn)對(duì)圖片進(jìn)行局部切割的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-12-12對(duì)pandas replace函數(shù)的使用方法小結(jié)
今天小編就為大家分享一篇對(duì)pandas replace函數(shù)的使用方法小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-05-05python 微信好友特征數(shù)據(jù)分析及可視化
這篇文章主要介紹了python 微信好友特征數(shù)據(jù)分析及可視化,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01windows python3安裝Jupyter Notebooks教程
這篇文章主要介紹了windows python3安裝Jupyter Notebooks教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-04-04Python線程池ThreadPoolExecutor使用方式
這篇文章主要介紹了Python線程池ThreadPoolExecutor使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02Python3.10.4激活venv環(huán)境失敗解決方法
這篇文章主要介紹了Python3.10.4激活venv環(huán)境失敗解決方法的相關(guān)資料,需要的朋友可以參考下2023-01-01NumPy數(shù)組創(chuàng)建方法與索引訪問(wèn)詳解
這篇文章主要介紹了NumPy數(shù)組創(chuàng)建方法與索引訪問(wèn),NumPy 中的核心數(shù)據(jù)結(jié)構(gòu)是 ndarray,它代表多維數(shù)組,NumPy 提供了多種方法來(lái)創(chuàng)建 ndarray 對(duì)象,文中通過(guò)代碼示例講解的非常詳細(xì),需要的朋友可以參考下2024-05-05