Python函數(shù)式編程之面向過程面向?qū)ο蠹昂瘮?shù)式簡析
Python 函數(shù)式編程
Python 不是純粹的函數(shù)式語言,但你可以使用 Python 進(jìn)行函數(shù)式編程
典型的聽君一席話,如聽一席話,說白了就是 Python 具備函數(shù)式編程的特性,
so,可以借用函數(shù)式語言的設(shè)計(jì)模式和編程技術(shù),把代碼寫成函數(shù)式編程的樣子
一般此時(shí)我會(huì)吹噓一下,函數(shù)式代碼比較簡潔和優(yōu)雅~
好了,已經(jīng)吹噓完了。
以上內(nèi)容都屬于講道理的范圍,那在 Python 中有哪些適合函數(shù)式編程的技能點(diǎn)
又有哪些不適的點(diǎn)呢?
下述 2 點(diǎn)先有個(gè)印象就行
優(yōu)點(diǎn):生成器表達(dá)式,這個(gè)后面咱會(huì)反復(fù)提及,具備很多高階函數(shù),例如 reduce
,map
,filter
三巨頭。
缺點(diǎn):沒有無限遞歸等~
如果你去百度 “什么是函數(shù)式編程”,很多地方會(huì)給出答案
函數(shù)式編程:允許把函數(shù)本身作為參數(shù)傳入另一個(gè)函數(shù),還允許返回一個(gè)函數(shù)。
有道理!
其實(shí)函數(shù)式編程就是在函數(shù)中定義表達(dá)式和實(shí)現(xiàn)表達(dá)式的求職,說白了就是用函數(shù)落地你的代碼。
看起來好像是廢話,它還有一個(gè)補(bǔ)充的說明,在函數(shù)式編程中要避免狀態(tài)變化和使用可變對(duì)象。
其中避免狀態(tài)變化 重點(diǎn)要關(guān)注賦值語句以及它如何改變狀態(tài),因此你在函數(shù)式編程中,不會(huì)看到 global
,nolocal
等內(nèi)容。
同一案例的不同寫法,展示函數(shù)式編程
概念與原理都是比較抽象的,咱還是少說概念,這個(gè)留到未來你自己總結(jié)就好,直接展示源碼差異。
計(jì)算 1~100 內(nèi),計(jì)算 5 與 7 的倍數(shù)之和
面向過程的寫法
count = 0 for num in range(1, 101): if num % 5 == 0 or num % 7 == 0: count += num print(count)
在面向過程的寫法中,邏輯都是從上向下進(jìn)行運(yùn)行的,例如 num
從 1 數(shù)到 100,如果對(duì) 5 或者對(duì) 7 取余等于 0,那表示可以整除,然后將 count
與對(duì)應(yīng)的 num
相加,得到最后的余數(shù)。
這種思路是純面向過程的寫法,一般我們學(xué)習(xí)編程時(shí),首先學(xué)會(huì)的就是該類寫法。
面向?qū)ο蟮膶懛?/h3>
該類寫法有兩種,一種是使用 Python 內(nèi)置的列表實(shí)現(xiàn),一種是自己聲明一個(gè)類來實(shí)現(xiàn)。
第一種寫法:
count = list() for num in range(1, 101): if num % 5 == 0 or num % 7 == 0: count.append(num) print(sum(count))
在上述寫法中,變量 count
聲明一個(gè) list
,即列表對(duì)象,但是整理看起來還是有些過程式編程語言的影子。
例如最后的 sum(count)
的使用就有些奇怪,看不出來面向?qū)ο蟮挠白印?/p>
接下來,咱們創(chuàng)建一個(gè)自定義的類,進(jìn)行邏輯實(shí)現(xiàn)。
class My_List_Sum(list): def sum(self): count = 0 for n in self: count += n return count count = My_List_Sum() for num in range(1, 101): if num % 5 == 0 or num % 7 == 0: count.append(num) print(count.sum())
上述代碼,我們自行實(shí)現(xiàn)了一個(gè) My_List_Sum
類,讓它繼承自 list
,此時(shí)你應(yīng)該明白,list
就是一個(gè)類名,然后在類的內(nèi)部實(shí)現(xiàn)了 sum
方法,再調(diào)用該對(duì)象的 sum
方法,完美的應(yīng)用了面向?qū)ο蟮膶懛ā?/p>
接下來進(jìn)入正題,函數(shù)式編程的落地實(shí)現(xiàn)
在正式編寫前,需要回憶一些基礎(chǔ)知識(shí),例如 lambda
表達(dá)式以及列表相加。
判斷一個(gè)數(shù)字是 5 或者 7 的倍數(shù), lambda
寫法如下:
multiple = lambda x: x % 5 == 0 or x % 7 == 0 a = multiple(3) # False b = multiple(5) # True c = multiple(7) # False print(a, b, c)
列表相加代碼如下:
print([1]+[2]) # [1,2]
有了上述內(nèi)容,可以編寫一個(gè)遞歸函數(shù),實(shí)現(xiàn)對(duì)應(yīng)的邏輯,代碼的說明已經(jīng)添加到注釋中。
def tool(n: int, end: int, filter_func) -> list: """返回一個(gè)篩選之后的列表 :param n: 起始值 :param end: 終止值 :param filter_func: 判斷表達(dá)式 """ # 如果到達(dá)上限,直接返回空列表 if n == end: return [] # 如果滿足過濾條件,返回該值與下一個(gè)值組成的列表 if filter_func(n): return [n] + tool(n + 1, end, filter_func) else: # 不滿足過濾條件,直接返回下一個(gè)值 return tool(n + 1, end, filter_func) # 測(cè)試代碼 ret = tool(1, 101, lambda x: x % 5 == 0 or x % 7 == 0) print(ret) print(sum(ret))
上述代碼即為求和的函數(shù)式實(shí)現(xiàn),其中部分邏輯如下:
- 給定初始值與上限值,當(dāng)?shù)闹档扔谏舷拗禃r(shí),返回空列表,即運(yùn)行結(jié)束;
- 傳入一個(gè)判斷條件,本案例中為一個(gè) lambda 表達(dá)式,用于判斷 5 和 7 的倍數(shù);
- 當(dāng)滿足條件時(shí),進(jìn)行的是相加+迭代工作,當(dāng)不滿足條件時(shí),直接進(jìn)入下一次迭代。
當(dāng)然還有一種函數(shù)式編程的寫法,代碼如下:
print(sum(n for n in range(1, 101) if n % 5 == 0 or n % 7 == 0))
這里用到的生成器后文會(huì)進(jìn)行說明。
Python 函數(shù)式編程的特點(diǎn)
在 Python 中,函數(shù)即對(duì)象,例如聲明一個(gè)函數(shù)之后,你可以調(diào)用其屬性。
下述代碼展示的即為函數(shù)對(duì)象的屬性,其余內(nèi)容可以自行再做測(cè)試。
def my_func(var1, var2, **kw): return var1 + var2 print(type(my_func)) # <class 'function'> print(my_func.__code__) print(my_func.__dict__) print(my_func.__code__.co_code) print(my_func.__code__.co_filename) print(my_func.__code__.co_argcount)
函數(shù)式編程之所以高效,其中一個(gè)很重要的原因就是延遲計(jì)算,也叫做惰性求值,這些在后面都將逐步展開,現(xiàn)在依舊是接收一下印象概念。
正是因?yàn)楹瘮?shù)即對(duì)象,所有才有本文開篇那段對(duì)函數(shù)式編程的定義。
函數(shù)可以使用其它函數(shù)作為參數(shù),或者返回另一個(gè)函數(shù),所以在實(shí)際編碼過程中,我們將會(huì)把函數(shù)轉(zhuǎn)換成其它代碼中的 “對(duì)象”,從而實(shí)現(xiàn)函數(shù)式編程。
接下來咱們要接觸一下 Python 中的純函數(shù)概念以及應(yīng)用。
純函數(shù)
純函數(shù)是一個(gè)概念,也就是讓函數(shù)不會(huì)對(duì)函數(shù)外作用域產(chǎn)生影響,即作用域?yàn)楸镜亍?/p>
說簡單點(diǎn),就是在函數(shù)內(nèi)部避免賦值操作,當(dāng)然類似 global
等關(guān)鍵字也避免使用。
針對(duì)此,lambda
表達(dá)式就是純函數(shù)。
首先查看一個(gè)純函數(shù)的例子:
def my_func(num: int) -> int: return num * 100
上述代碼中函數(shù)的返回值僅與 num
有關(guān),滿足下面兩個(gè)條件:
- 沒有改變?nèi)肿兞浚?/li>
- 沒有更新可變數(shù)據(jù)結(jié)構(gòu),例如列表,字典。
接觸完畢純函數(shù)概念之后,下面了解一下函數(shù)作為對(duì)象的落地應(yīng)用。
在 Python 中聲明一個(gè)類,默認(rèn)會(huì)攜帶部分內(nèi)置的方法,例如:
from typing import Callable # 聲明一個(gè)類,該類無意義,僅測(cè)試使用 class Ext: # 傳入的函數(shù),可攜帶1~2個(gè)參數(shù) def __init__(self, test_demo: Callable[[int], int]) -> None: self.func = test_demo # 返回結(jié)果擴(kuò)大2倍 def __call__(self, arg: int) -> int: return self.func(arg) * 2 def one_func(var): return var + 1 def two_func(var): return var * 3 def three_func(var): return var a = Ext(one_func) print(a(3)) # 8 b = Ext(two_func) print(b(3)) # 18 c = Ext(three_func) print(c(3)) # 6
上述代碼使用了一個(gè)新的模塊 typing
,該模塊是 Python 3.5 之后新增的模塊,主要為 Python 提供靜態(tài)類型的檢查 。
本案例中導(dǎo)入的是回調(diào)函數(shù) Callable
,格式如下:
Callable[[Arg1Type, Arg2Type],ReturnType]
其中內(nèi)部中括號(hào) Arg1Type
是參數(shù)類型,ReturnType
為返回值類型。
上述三個(gè)函數(shù)的簽名都與 Callable
定義的一致,所以都可以作為 test_demo
參數(shù)的值去傳遞。
以上就是Python函數(shù)式編程之面向過程面向?qū)ο蠹昂瘮?shù)式簡析的詳細(xì)內(nèi)容,更多關(guān)于Python函數(shù)式編程面向過程面向?qū)ο蠹昂瘮?shù)式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
用Python爬取某乎手機(jī)APP數(shù)據(jù)
最近爬取的數(shù)據(jù)都是網(wǎng)頁端,今天來教大家如何爬取手機(jī)端app數(shù)據(jù)(本文以ios蘋果手機(jī)為例,其實(shí)安卓跟ios差不多)! 本文將以『某乎』為實(shí)戰(zhàn)案例,手把手教你從配置到代碼一步一步的爬取App數(shù)據(jù),需要的朋友可以參考下2021-06-06Python中實(shí)現(xiàn)優(yōu)雅的switch操作的方法小結(jié)
這篇文章主要為大家詳細(xì)介紹了如何在Python中優(yōu)雅地實(shí)現(xiàn)?switch?操作,并提供豐富的示例代碼,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02關(guān)于Django ForeignKey 反向查詢中filter和_set的效率對(duì)比詳解
今天小編就為大家分享一篇關(guān)于Django ForeignKey 反向查詢中filter和_set的效率對(duì)比詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-12-12vscode和Anaconda安裝以及相關(guān)環(huán)境配置指南
Anaconda是一個(gè)開源的python發(fā)行版本,是現(xiàn)在比較流行的python數(shù)據(jù)科學(xué)平臺(tái),可以對(duì)python的科學(xué)包做到有效管理,這篇文章主要給大家介紹了關(guān)于vscode和Anaconda安裝以及相關(guān)環(huán)境配置指南的相關(guān)資料,需要的朋友可以參考下2023-11-11Python面向?qū)ο髮?shí)現(xiàn)一個(gè)對(duì)象調(diào)用另一個(gè)對(duì)象操作示例
這篇文章主要介紹了Python面向?qū)ο髮?shí)現(xiàn)一個(gè)對(duì)象調(diào)用另一個(gè)對(duì)象操作,結(jié)合實(shí)例形式分析了Python對(duì)象的定義、初始化、調(diào)用等相關(guān)操作技巧,需要的朋友可以參考下2019-04-04PyTorch中的參數(shù)類torch.nn.Parameter()詳解
這篇文章主要給大家介紹了關(guān)于PyTorch中torch.nn.Parameter()的相關(guān)資料,要內(nèi)容包括基礎(chǔ)應(yīng)用、實(shí)用技巧、原理機(jī)制等方面,文章通過實(shí)例介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02Python新手入門webpy小應(yīng)用開發(fā)
本文主要介紹了Python新手入門webpy小應(yīng)用開發(fā),文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-07-07python機(jī)器學(xué)習(xí)之神經(jīng)網(wǎng)絡(luò)實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了python機(jī)器學(xué)習(xí)之神經(jīng)網(wǎng)絡(luò)的實(shí)現(xiàn)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-10-10Python實(shí)現(xiàn)隨機(jī)森林回歸與各自變量重要性分析與排序
這篇文章主要為大家詳細(xì)介紹了在Python環(huán)境中,實(shí)現(xiàn)隨機(jī)森林(Random Forest,RF)回歸與各自變量重要性分析與排序的過程,感興趣的小伙伴可以了解一下2023-02-02