偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

10分鐘學(xué)會(huì)Python函數(shù)式編程

開(kāi)發(fā) 后端
在這篇文章里,你將學(xué)會(huì)什么是函數(shù)范式以及如何使用Python進(jìn)行函數(shù)式編程。你也將了解列表推導(dǎo)和其它形式的推導(dǎo)。

???

在這篇文章里,你將學(xué)會(huì)什么是函數(shù)范式以及如何使用Python進(jìn)行函數(shù)式編程。你也將了解列表推導(dǎo)和其它形式的推導(dǎo)。

函數(shù)范式

在命令式范式中,通過(guò)為計(jì)算機(jī)提供一系列指令然后執(zhí)行它們來(lái)完成任務(wù)。在執(zhí)行這些指令時(shí),可以改變某些狀態(tài)。例如,假設(shè)你最初將A設(shè)置為5,然后更改A的值。這時(shí)在變量?jī)?nèi)部值的意義上,你改變了A的狀態(tài)。

在函數(shù)式范式中,你不用告訴計(jì)算機(jī)做什么而是告訴他這個(gè)東西是什么。比如數(shù)字的***公約數(shù)是什么,從1到n的乘積是什么等等。

因此,變量不能變化。一旦你設(shè)置了一個(gè)變量,它就永遠(yuǎn)保持這種狀態(tài)(注意,在純函數(shù)式語(yǔ)言中,它們不是變量)。因此,函數(shù)式編程沒(méi)有副作用。副作用指的是函數(shù)改變它自己以外的東西。讓我們看一些典型Python代碼的示例:

???

這段代碼的輸出是5。在函數(shù)式范式中,改變變量是一個(gè)很大的禁忌,并且具有影響其范圍之外事物的功能也是一個(gè)很大的禁忌。函數(shù)唯一能做的就是計(jì)算一些東西并將其作為結(jié)果返回。

現(xiàn)在你可能會(huì)想:“沒(méi)有變量,沒(méi)有副作用?為什么這樣好?“這個(gè)問(wèn)題問(wèn)得好,我相信大多數(shù)人對(duì)此感到疑惑。

如果使用相同的參數(shù)調(diào)用函數(shù)兩次,則保證返回相同的結(jié)果。如果你已經(jīng)學(xué)習(xí)了數(shù)學(xué)函數(shù),你就會(huì)知道這個(gè)好處。這稱為參照透明度。由于函數(shù)沒(méi)有副作用,如果你正在構(gòu)建一個(gè)計(jì)算某些事情的程序,你可以加速程序。如果每次調(diào)用func(2)都返回3,我們可以將它存儲(chǔ)在表中,這可以防止程序重復(fù)運(yùn)行相同的功能。

通常,在函數(shù)式編程中,我們不使用循環(huán)。我們使用遞歸。遞歸是一個(gè)數(shù)學(xué)概念,通常意味著“自我調(diào)用”。使用遞歸函數(shù),該函數(shù)將其自身作為子函數(shù)重復(fù)調(diào)用。這是Python中遞歸函數(shù)的一個(gè)很好的例子:

???

有些編程語(yǔ)言也具有惰性。這意味著他們直到***一秒才計(jì)算或做任何事情。如果你編寫(xiě)一些代碼來(lái)執(zhí)行2 + 2,函數(shù)程序只會(huì)在你真正需要使用結(jié)果時(shí)計(jì)算出來(lái)。我們很快就會(huì)在Python中探索惰性。

Map

為了理解,我們先來(lái)看看迭代是什么。通??梢缘膶?duì)象是列表或數(shù)組,但Python有許多不同的類(lèi)型可以迭代。你甚至可以創(chuàng)建自己的對(duì)象,這些對(duì)象可以通過(guò)實(shí)現(xiàn)魔術(shù)方法進(jìn)行迭代。魔術(shù)方法就像是一個(gè)API,可以幫助你的對(duì)象變得更加Pythonic。您需要實(shí)現(xiàn)2個(gè)魔術(shù)方法才能使對(duì)象成為可迭代的:

???

***個(gè)魔術(shù)方法“__iter__”(注:這里是雙下劃線)返回迭代對(duì)象,這通常在循環(huán)開(kāi)始時(shí)使用?!盻_next__“返回下一個(gè)對(duì)象。

讓我們快速進(jìn)入一個(gè)終端調(diào)用上面的代碼:

???

運(yùn)行將會(huì)打印出

???

在Python中,迭代器是一個(gè)只有__iter__魔術(shù)方法的對(duì)象。這意味著您可以訪問(wèn)對(duì)象中的位置,但不能遍歷該對(duì)象。一些對(duì)象將具有魔術(shù)方法__next__而不是__iter__魔術(shù)方法,例如集合(在本文后面討論)。對(duì)于本文,我們假設(shè)我們接觸的所有內(nèi)容都是可迭代的對(duì)象。

現(xiàn)在我們知道什么是可迭代對(duì)象了,讓我們回到map函數(shù)。 map函數(shù)允許我們將函數(shù)應(yīng)用于iterable中的每一項(xiàng)。 Map需要2個(gè)輸入,它們分別是要應(yīng)用的函數(shù)和可迭代對(duì)象。

???

假設(shè)我們有一個(gè)數(shù)字列表,如下所示:

???

我們想要對(duì)每個(gè)數(shù)字進(jìn)行平方,我們可以編寫(xiě)如下代碼:

???

Python中函數(shù)式的函數(shù)是具有惰性的。如果我們不使用“l(fā)ist”,該函數(shù)將存儲(chǔ)iterable的定義,而不是列表本身。我們需要明確告訴Python“把它變成一個(gè)列表”供我們使用。

在Python中突然從非惰性求值轉(zhuǎn)向惰性求值有點(diǎn)奇怪。如果你在函數(shù)式思維方式中考慮得更多,而不是命令式思維方式,那么你最終會(huì)習(xí)慣它。

現(xiàn)在寫(xiě)一個(gè)像“square(num)”這樣的普通函數(shù)雖然很好,但卻是不對(duì)的。我們必須定義一個(gè)完整的函數(shù)才能在map中使用它?好吧,我們可以使用lambda(匿名)函數(shù)在map中定義一個(gè)函數(shù)。

Lambda表達(dá)式

lambda表達(dá)式是一個(gè)只有一行的函數(shù)。舉個(gè)例子,這個(gè)lambda表達(dá)式對(duì)給定的數(shù)字進(jìn)行平方:

???

讓我們運(yùn)行它:

???

這看起來(lái)不像一個(gè)函數(shù)嗎?

嗯,這有點(diǎn)令人困惑,但可以解釋。我們將一些東西分配給變量“square”。那這個(gè)呢:

???

告訴Python這是一個(gè)lambda函數(shù),輸入叫做x。冒號(hào)之后的任何內(nèi)容都是您對(duì)輸入所做的操作,它會(huì)自動(dòng)返回結(jié)果。

簡(jiǎn)化我們的square程序到只有一行代碼,我們可以這樣做:

???

所以在lambda表達(dá)式中,所有參數(shù)都在左邊,你要用它們做的東西在右邊。它有點(diǎn)亂。但事實(shí)是,編寫(xiě)只有其他函數(shù)式程序員才能閱讀的代碼會(huì)有一定的樂(lè)趣。此外,使用一個(gè)函數(shù)并將其轉(zhuǎn)換為一行代碼是非??岬?。

Reduce

Reduce是一個(gè)將迭代變成一個(gè)東西的函數(shù)。通常,你可以在列表上使用reduce函數(shù)執(zhí)行計(jì)算以將其減少到一個(gè)數(shù)字。 Reduce看起來(lái)像這樣:

???

我們經(jīng)常會(huì)使用lambda表達(dá)式作為函數(shù)。

列表的乘積是每個(gè)單獨(dú)的數(shù)字相乘。要做到這一點(diǎn)你將編寫(xiě)如下代碼:

???

但是使用reduce你可以這樣寫(xiě):

???

獲得相同的功能,代碼更短,并且在使用函數(shù)式編程的情況下更整潔。(注:reduce函數(shù)在Python3中已不是內(nèi)置函數(shù),需要從functools模塊中導(dǎo)入)

Filter

filter函數(shù)采用可迭代的方式,并過(guò)濾掉你在該可迭代中不需要的所有內(nèi)容。

通常,filter需要一個(gè)函數(shù)和一個(gè)列表。它將函數(shù)應(yīng)用于列表中的每一項(xiàng),如果該函數(shù)返回True,則不執(zhí)行任何操作。如果返回False,則從列表中刪除該項(xiàng)。

語(yǔ)法如下:

???

讓我們看一個(gè)小例子,沒(méi)有filter我們會(huì)寫(xiě):

???

使用filter,可以這樣寫(xiě):

???

高階函數(shù)

高階函數(shù)可以將函數(shù)作為參數(shù)并返回函數(shù)。一個(gè)非常簡(jiǎn)單的例子如下:

???

第二個(gè)返回函數(shù)的例子:

???

開(kāi)頭我說(shuō)過(guò)純函數(shù)式編程語(yǔ)言沒(méi)有變量。更高階的函數(shù)使這變得更容易。

Python中的所有函數(shù)都是一等公民。一等公民被定義為具有以下一個(gè)或多個(gè)特征:


  •     在運(yùn)行時(shí)創(chuàng)建
  •     在數(shù)據(jù)結(jié)構(gòu)中分配變量或元素
  •     作為函數(shù)的參數(shù)傳遞
  •     作為函數(shù)的結(jié)果返回
  •     Python中的所有函數(shù)都可以用作高階函數(shù)。

Partial application

Partial application(也稱為閉包)有點(diǎn)奇怪,但非??帷D梢栽诓惶峁┧璧乃袇?shù)的情況下調(diào)用函數(shù)。讓我們?cè)谝粋€(gè)例子中看到這一點(diǎn)。我們想要?jiǎng)?chuàng)建一個(gè)函數(shù),它接受2個(gè)參數(shù),一個(gè)基數(shù)和一個(gè)指數(shù),并返回指數(shù)冪的基數(shù),如下所示:

???

現(xiàn)在我們想要一個(gè)專用的平方函數(shù),使用冪函數(shù)計(jì)算出數(shù)字的平方:

???

這有效,但如果我們想要一個(gè)立方體功能呢?或者求四次方的功能呢?我們可以繼續(xù)寫(xiě)下它們嗎?好吧,你可以。但程序員很懶的。如果你一遍又一遍地重復(fù)同樣的事情,這表明有一種更快的方法來(lái)加快速度,這將使你不再重復(fù)。我們可以在這里使用閉包。讓我們看一個(gè)使用閉包的square函數(shù)的示例:

???

是不是很酷!我們可以只使用1個(gè)參數(shù)來(lái)調(diào)用需要2個(gè)參數(shù)的函數(shù)。

我們還可以使用一個(gè)循環(huán)來(lái)生成一個(gè)冪函數(shù),該函數(shù)實(shí)現(xiàn)從立方體一直到1000的冪。

???

函數(shù)式編程不是pythonic

您可能已經(jīng)注意到了,我們想要在函數(shù)式編程中做的很多事情都圍繞著列表。除了reduce函數(shù)和閉包之外,您看到的所有函數(shù)都會(huì)生成列表。 Guido(Python之父)不喜歡Python中的函數(shù)式,因?yàn)镻ython已經(jīng)有了自己生成列表的方法。

如果你在Python的交互環(huán)境下寫(xiě)入”import this“,你將會(huì)得到:

???

這是Python之禪。這是一首關(guān)于Pythonic意味著什么的詩(shī)。我們想要涉及的部分是:

There should be one — and preferably only one — obvious way to do it.(應(yīng)該盡量找到一種,***是唯一一種明顯的解決方案)

在Python中,map和filter可以執(zhí)行與列表推導(dǎo)(下面討論)相同的操作。這打破了Python之禪的一個(gè)規(guī)則,因此函數(shù)式編程的這些部分不被視為“pythonic”。


另一個(gè)話題是Lambda。在Python中,lambda函數(shù)是一個(gè)普通函數(shù)。 Lambda是語(yǔ)法糖。這兩種說(shuō)法是等價(jià)的。

???

普通函數(shù)可以執(zhí)行l(wèi)ambda函數(shù)可以執(zhí)行的所有操作,但它不能以相反的方式工作。 lambda函數(shù)不能完成普通函數(shù)可以執(zhí)行的所有操作。

這是一個(gè)簡(jiǎn)短的論證,為什么函數(shù)式編程不能很好地適應(yīng)整個(gè)Python生態(tài)系統(tǒng)。你可能已經(jīng)注意到我之前提到了列表推導(dǎo),我們現(xiàn)在將討論它們。

列表推導(dǎo)

前面,我提到過(guò)你可以用map或filter做的任何事情,你可以用列表推導(dǎo)。列表推導(dǎo)是一種在Python中生成列表的方法。語(yǔ)法是:

???

讓我們對(duì)列表中的每個(gè)數(shù)字進(jìn)行平方,例如:

?[[250871]]??

我們可以看到如何將函數(shù)應(yīng)用于列表中的每一項(xiàng)。我們?nèi)绾螒?yīng)用filter呢?看看前面的代碼:

???

我們可以將其轉(zhuǎn)換成一個(gè)列表推導(dǎo),像這樣:

???

列表支持if這樣的語(yǔ)句。您不再需要將一百萬(wàn)個(gè)函數(shù)應(yīng)用于某些東西以獲得您想要的東西。事實(shí)上,如果你想嘗試生成某種列表,那么使用列表推導(dǎo)看起來(lái)會(huì)更清晰,更容易。如果我們想要將列表中每個(gè)0以下的數(shù)字平方怎么辦?有了lambda,map和filter你會(huì)寫(xiě):

???

這似乎很長(zhǎng)很復(fù)雜。通過(guò)列表推導(dǎo),它只是:

???

列表推導(dǎo)僅適用于列表。map,filter適合任何可迭代的對(duì)象,那么這有什么用呢?你可以對(duì)你遇到的任何可迭代對(duì)象使用任何推導(dǎo)。

其他推導(dǎo)

你可以為任何可迭代對(duì)象創(chuàng)建一個(gè)推導(dǎo)。

可以使用推導(dǎo)生成任何可迭代的對(duì)象。從Python 2.7開(kāi)始,您甚至可以生成字典(hashmap)。

如果它是可迭代的,則可以生成它。讓我們看一下***一組的例子。

???


  •     set是一個(gè)元素列表,在該列表中沒(méi)有元素重復(fù)兩次。
  •     set中的元素沒(méi)有順序。

???

您可能會(huì)注意到set(集合)與dict(字典)具有相同的花括號(hào)。 Python非常聰明。根據(jù)你是否為dict提供值,它會(huì)知道你是在寫(xiě)dict推導(dǎo)還是set推導(dǎo)。

總結(jié)

函數(shù)式編程美觀而純粹。函數(shù)式代碼可以很干凈,但也可能很亂。一些Python程序員不喜歡Python中的函數(shù)式編程。但我認(rèn)為,你應(yīng)該在解決問(wèn)題時(shí),使用***工具。

責(zé)任編輯:龐桂玉 來(lái)源: 今日頭條
相關(guān)推薦

2018-02-01 14:15:00

Python函數(shù)

2019-07-18 16:32:06

Python函數(shù)數(shù)據(jù)

2021-07-15 06:43:11

Bash調(diào)試腳本

2013-09-13 14:08:01

2024-03-04 15:19:52

Python編程內(nèi)建函數(shù)

2009-11-04 13:12:33

VB.NET面向?qū)ο缶?/a>

2022-03-08 08:39:22

gRPC協(xié)議云原生

2018-08-30 09:01:28

Web服務(wù)器Windows 10

2015-03-12 17:01:33

MySQLMySQL亂碼編碼轉(zhuǎn)換

2024-07-10 18:55:09

Python定時(shí)

2016-12-22 21:47:04

SEDLinuxUnix

2020-05-22 10:20:27

Shiro架構(gòu)字符串

2011-08-24 09:13:40

編程

2020-11-09 09:59:50

Ajax技術(shù)

2022-05-30 08:34:49

PythonSQL

2009-11-12 16:25:35

Oracle嵌套循環(huán)

2009-10-21 18:19:36

VB.NET實(shí)現(xiàn)拖放

2020-10-13 18:22:58

DevOps工具開(kāi)發(fā)

2014-08-08 09:30:04

android scrollview

2021-04-23 09:50:41

topLinux命令
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)