Python筆記(二):高級(jí)特性之高階函數(shù)

0x00. 概述

在熟悉了Python基礎(chǔ)知識(shí)后螟蝙,我們已經(jīng)可以做一些腳本開(kāi)發(fā),或者簡(jiǎn)單的程序副瀑。然而弓熏,當(dāng)我們開(kāi)發(fā)較為復(fù)雜的程序時(shí),僅使用基礎(chǔ)知識(shí)內(nèi)容就會(huì)顯得比較吃力糠睡。這時(shí)挽鞠,了解Python中的一些高級(jí)特性會(huì)使我們的開(kāi)發(fā)過(guò)程變得簡(jiǎn)單和快樂(lè)。

閱讀本篇文章,筆者默認(rèn)您已經(jīng)掌握Python基礎(chǔ)知識(shí)信认。如果您對(duì)Python還不了解材义,請(qǐng)參考Python筆記(一):基礎(chǔ)知識(shí)

PS:本打算把幾個(gè)高級(jí)特性都寫(xiě)到一篇文章里,但是后來(lái)想了想如果真這樣的話(huà)文章就太長(zhǎng)了嫁赏,索性分開(kāi)來(lái)講其掂,獨(dú)自成文,也可以講的更細(xì)一點(diǎn)潦蝇。

0x01. 介紹

在數(shù)學(xué)和計(jì)算機(jī)科學(xué)中款熬,高階函數(shù)是至少滿(mǎn)足下列一個(gè)條件的函數(shù):

接受一個(gè)或多個(gè)函數(shù)作為輸入

輸出一個(gè)函數(shù)

——摘自百度百科

已經(jīng)不記得數(shù)學(xué)中的高階函數(shù)是個(gè)什么鬼了(請(qǐng)?jiān)徫沂莻€(gè)學(xué)渣~)。但是在Python中高階函數(shù)幾乎隨處可見(jiàn)攘乒。最經(jīng)典的莫過(guò)于map/reduce兩個(gè)函數(shù)了贤牛,這兩個(gè)函數(shù)后面講,我們先看一個(gè)簡(jiǎn)單的例子:

def f(x):
    return x * x

def h(func, x):
    return func(x) * func(x)
    
print(h(f, 2)) # 打印結(jié)果是: 16 

這段代碼中函數(shù)h就是一個(gè)高階函數(shù)持灰,因?yàn)樗牡谝粋€(gè)參數(shù)是一個(gè)函數(shù)(即接受一個(gè)函數(shù)作為輸入盔夜,滿(mǎn)足高階函數(shù)的第一個(gè)條件)。

再來(lái)看一個(gè):

def m(x):
    def n():
        return x * x
    return n
    
print(m(2)()) # 打印結(jié)果是: 4

是的堤魁,你沒(méi)有看錯(cuò)喂链!在函數(shù)m內(nèi)部定義了一個(gè)子函數(shù)n,并且將該函數(shù)作為返回值返回妥泉。

當(dāng)我們調(diào)用m(2)時(shí)椭微,返回值是函數(shù)n,那么m(2)()就是對(duì)函數(shù)n的調(diào)用盲链。
如果還不理解蝇率,可以將print(m(2)())拆成兩行:

sub_func = m(2)
print(sub_func())

這里還涉及了一個(gè)知識(shí)點(diǎn):

在Python中,對(duì)象和方法都是變量刽沾。

舉例說(shuō)明:

def say_hello(name):
    print('Hello, %s' % name)
 
sh = say_hello # 將函數(shù)變量賦值給sh變量
sh('lovexiaov') # 打印結(jié)果是: Hello, lovexiaov

say_hello = 3 # 給函數(shù)變量賦值
say_hello('lovexiaov') # TypeError: 'int' object is not callable

閉包

說(shuō)到高階函數(shù)本慕,就不得不提閉包,先來(lái)看一下Python中閉包的定義:

如果在一個(gè)內(nèi)部函數(shù)里侧漓,對(duì)在外部作用域(但不是在全局作用域)的變量進(jìn)行引用锅尘,那么內(nèi)部函數(shù)就被認(rèn)為是閉包(closure)。

我們還是舉個(gè)例子:

def closure():
    x = 5

    def sub():
        return x * x

    return sub

如上布蔗,在內(nèi)部函數(shù)sub中包含了對(duì)函數(shù)closure中局部變量x的引用藤违,這就是閉包。

匿名函數(shù)/lambda

在介紹高階函數(shù)的用處之前纵揍,還需要了解另一個(gè)概念顿乒,沒(méi)錯(cuò),就是匿名函數(shù)泽谨。Python語(yǔ)言支持使用?lambda 表達(dá)式作為匿名函數(shù)璧榄。

國(guó)際慣例特漩,代碼奉上:

def use_lambda():
    return lambda x: x * x

print(use_lambda()(5)) # 打印結(jié)果是25

來(lái)看重點(diǎn)代碼lambda x: x * x,這行代碼就是一個(gè)完整的函數(shù)犹菱。使用lambda聲明該行代碼是一個(gè)lambda表達(dá)式拾稳,緊跟在后面的是函數(shù)的參數(shù),多個(gè)參數(shù)用逗號(hào),分割腊脱;然后使用冒號(hào):分割開(kāi)參數(shù)和函數(shù)體访得。該表達(dá)式拆解成普通的函數(shù)是這樣的:

def func(x):
    return x * x

怎么樣,使用lambda表達(dá)式是不是讓代碼看起來(lái)整潔了許多陕凹,有強(qiáng)迫癥的同學(xué)們悍抑?

map函數(shù)

前面舉了很多高階函數(shù)的例子,那么使用高階函數(shù)到底有什么好處呢杜耙?是為了讓自己顯得高大上搜骡?這個(gè)問(wèn)題可以先留著,等看完下面的例子后自己找答案佑女。

map函數(shù)是Python中的內(nèi)置函數(shù)记靡,官方文檔定義(Python 3.5版本,不適合2.x版本)為:

map(function, iterable, ...)

Return an iterator that applies function to every item of iterable, yielding the results.

咳咳团驱,是時(shí)候展示我粗大的英語(yǔ)了摸吠。大致的意思是“function函數(shù)會(huì)作用于可迭代對(duì)象的每一個(gè)元素,生成結(jié)果嚎花,并返回一個(gè)迭代器”寸痢。至于yield,我們可以暫時(shí)形象的理解為噎住紊选,下面會(huì)進(jìn)行講解啼止。

現(xiàn)在假設(shè)我們要對(duì)一個(gè)數(shù)組中的每個(gè)元素求平方,并生成一個(gè)新數(shù)組返回兵罢,看代碼:

iter = map(lambda x: x * x, [1, 2, 3, 4])
for i in iter:
    print('i : %d' % i)

代碼依然這么簡(jiǎn)潔献烦,而且意思很明確,雖然我們可以自己寫(xiě)函數(shù)實(shí)現(xiàn):

def get_square(l):
    L = []
    for i in l:
        L.append(i * i)
    return L

但是可讀性就差很多了卖词,在上一篇文章中我們就提到了Python的設(shè)計(jì)原則就是優(yōu)雅仿荆,明確,簡(jiǎn)單坏平,這里是不是一個(gè)很好的體現(xiàn)?

迭代器有一個(gè)特點(diǎn)锦亦,就是所有的迭代器對(duì)象都可以作為next()內(nèi)置函數(shù)的參數(shù)調(diào)用舶替,每調(diào)用一次,就按角標(biāo)順序返回一個(gè)值杠园,還是用代碼講吧:

iter = map(lambda x: x * x, [1, 2, 3, 4])
print(next(iter)) # 打印值為:1
print(next(iter)) # 打印值為:4
print(next(iter)) # 打印值為:9
print(next(iter)) # 打印值為:16
print(next(iter)) # 拋出StopIteration 異常

怎么樣顾瞪,是不是有種被“噎住”的感覺(jué)啊,哈哈。

話(huà)說(shuō)回來(lái)陈醒,我們的Python語(yǔ)言也是一個(gè)“明明可以靠臉吃飯惕橙,卻偏要靠實(shí)力吃飯”的主,光優(yōu)雅钉跷,明確弥鹦,簡(jiǎn)單不夠,還必須得實(shí)用爷辙。下面我們來(lái)個(gè)更高級(jí)的:

r = map(lambda x, y: x + y, [1, 2, 3, 4], [5, 6, 7, 8])
print(r) # 打印結(jié)果:[6, 8, 10, 12]

0x02. 總結(jié)

在Python內(nèi)置函數(shù)和標(biāo)準(zhǔn)庫(kù)中彬坏,有不少都是高階函數(shù),合理利用這些函數(shù)可以使我們更便捷的開(kāi)發(fā)出功能強(qiáng)大的應(yīng)用膝晾。同時(shí)栓始,在我們的日常開(kāi)發(fā)中,合理使用高階函數(shù)會(huì)使我們的代碼更易于維護(hù)和有更高的可讀性血当。不要再猶豫了幻赚,開(kāi)始體驗(yàn)把!

0x03. 參考資料

廖雪峰Python教程

高階函數(shù)百科

閉包百科

lambda百科

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末臊旭,一起剝皮案震驚了整個(gè)濱河市落恼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌巍扛,老刑警劉巖领跛,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異撤奸,居然都是意外死亡吠昭,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)胧瓜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)矢棚,“玉大人,你說(shuō)我怎么就攤上這事府喳∑牙撸” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵钝满,是天一觀(guān)的道長(zhǎng)兜粘。 經(jīng)常有香客問(wèn)我,道長(zhǎng)弯蚜,這世上最難降的妖魔是什么孔轴? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮碎捺,結(jié)果婚禮上路鹰,老公的妹妹穿的比我還像新娘贷洲。我一直安慰自己,他們只是感情好晋柱,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布优构。 她就那樣靜靜地躺著,像睡著了一般雁竞。 火紅的嫁衣襯著肌膚如雪钦椭。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,071評(píng)論 1 285
  • 那天浓领,我揣著相機(jī)與錄音玉凯,去河邊找鬼。 笑死联贩,一個(gè)胖子當(dāng)著我的面吹牛漫仆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播泪幌,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼盲厌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了祸泪?” 一聲冷哼從身側(cè)響起吗浩,我...
    開(kāi)封第一講書(shū)人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎没隘,沒(méi)想到半個(gè)月后懂扼,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡右蒲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年阀湿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瑰妄。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡陷嘴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出间坐,到底是詐尸還是另有隱情灾挨,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布竹宋,位于F島的核電站劳澄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蜈七。R本人自食惡果不足惜秒拔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宪潮。 院中可真熱鬧溯警,春花似錦、人聲如沸狡相。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)尽棕。三九已至喳挑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間滔悉,已是汗流浹背伊诵。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留回官,地道東北人曹宴。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像歉提,于是被迫代替她去往敵國(guó)和親笛坦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容