黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

廖雪峰Python教程筆記(五)

系統(tǒng) 2065 0

廖雪峰Python教程筆記(五)

  • 7 函數(shù)式編程
    • 高階函數(shù)
      • map/reduce
      • filter:用于過(guò)濾序列。
        • sorted排序算法
    • 返回函數(shù):
    • 匿名函數(shù)
    • 裝飾器
    • 偏函數(shù)

7 函數(shù)式編程

函數(shù)是Python內(nèi)建支持的一種封裝,我們通過(guò)把大段代碼拆成函數(shù),通過(guò)一層一層的函數(shù)調(diào)用,就可以 把復(fù)雜任務(wù)分解成簡(jiǎn)單的任務(wù),這種分解可以稱之為面向過(guò)程的程序設(shè)計(jì) 。函數(shù)就是面向過(guò)程的程序設(shè)計(jì)的基本單元。

函數(shù)式編程 (請(qǐng)注意多了一個(gè)“式”字)——Functional Programming,雖然也可以歸結(jié)到面向過(guò)程的程序設(shè)計(jì),但其思想更接近數(shù)學(xué)計(jì)算。

計(jì)算機(jī)(Computer)和計(jì)算(Compute)的概念:

  • 在計(jì)算機(jī)的層次上,CPU執(zhí)行的是加減乘除的指令代碼,以及各種條件判斷和跳轉(zhuǎn)指令,所以,匯編語(yǔ)言是最貼近計(jì)算機(jī)的語(yǔ)言。
  • 而計(jì)算則指數(shù)學(xué)意義上的計(jì)算,越是抽象的計(jì)算,離計(jì)算機(jī)硬件越遠(yuǎn)。

對(duì)應(yīng)到編程語(yǔ)言,就是越低級(jí)的語(yǔ)言,越貼近計(jì)算機(jī),抽象程度低,執(zhí)行效率高,比如C語(yǔ)言;越高級(jí)的語(yǔ)言,越貼近計(jì)算,抽象程度高,執(zhí)行效率低,比如Lisp語(yǔ)言。

函數(shù)式編程就是一種抽象程度很高的編程范式,純粹的函數(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允許使用變量,因此, Python不是純函數(shù)式編程語(yǔ)言。

高階函數(shù)

高階函數(shù)英文叫Higher-order function

函數(shù)本身也可以賦值給變量,即:變量可以指向函數(shù)。
在這里插入圖片描述
在這里插入圖片描述
如果一個(gè)變量指向了一個(gè)函數(shù),那么,可否通過(guò)該變量來(lái)調(diào)用這個(gè)函數(shù)?用代碼驗(yàn)證一下:
在這里插入圖片描述
對(duì)于abs()這個(gè)函數(shù),完全可以把函數(shù)名abs看成變量,它指向一個(gè)可以計(jì)算絕對(duì)值的函數(shù)!
廖雪峰Python教程筆記(五)_第1張圖片
因?yàn)閍bs這個(gè)變量已經(jīng)不指向求絕對(duì)值函數(shù)而是指向一個(gè)整數(shù)10!

傳入函數(shù)
一個(gè)函數(shù)就可以接收另一個(gè)函數(shù)作為參數(shù),這種函數(shù)就稱之為 高階函數(shù)。

一個(gè)最簡(jiǎn)單的高階函數(shù):
在這里插入圖片描述
廖雪峰Python教程筆記(五)_第2張圖片

map/reduce

Python內(nèi)建了map()和reduce()函數(shù)。
map()函數(shù)接收兩個(gè)參數(shù),一個(gè)是函數(shù),一個(gè)是Iterable,map將傳入的函數(shù)依次作用到序列的每個(gè)元素,并把結(jié)果作為新的Iterator返回。
廖雪峰Python教程筆記(五)_第3張圖片
map()作為高階函數(shù),事實(shí)上它把運(yùn)算規(guī)則抽象了,因此,我們不但可以計(jì)算簡(jiǎn)單的f(x)=x2,還可以計(jì)算任意復(fù)雜的函數(shù),比如,把這個(gè)list所有數(shù)字轉(zhuǎn)為字符串:
在這里插入圖片描述

再看reduce的用法。reduce把一個(gè)函數(shù)作用在一個(gè)序列[x1, x2, x3, …]上,這個(gè)函數(shù)必須接收兩個(gè)參數(shù),reduce把結(jié)果繼續(xù)和序列的下一個(gè)元素做累積計(jì)算,其效果就是
在這里插入圖片描述
廖雪峰Python教程筆記(五)_第4張圖片
廖雪峰Python教程筆記(五)_第5張圖片
考慮到字符串str也是一個(gè)序列,對(duì)上面的例子稍加改動(dòng),配合map(),我們就可以寫出把str轉(zhuǎn)換為int的函數(shù):
廖雪峰Python教程筆記(五)_第6張圖片
還可以用lambda函數(shù)進(jìn)一步簡(jiǎn)化成:
廖雪峰Python教程筆記(五)_第7張圖片
假設(shè)Python沒(méi)有提供int()函數(shù),你完全可以自己寫一個(gè)把字符串轉(zhuǎn)化為整數(shù)的函數(shù),而且只需要幾行代碼!

filter:用于過(guò)濾序列。

filter()把傳入的函數(shù)依次作用于每個(gè)元素, 然后根據(jù)返回值是True還是False決定保留還是丟棄該元素。
例如,在一個(gè)list中,刪掉偶數(shù),只保留奇數(shù),可以這么寫:
廖雪峰Python教程筆記(五)_第8張圖片
把一個(gè)序列中的空字符串刪掉,可以這么寫:
廖雪峰Python教程筆記(五)_第9張圖片

sorted排序算法

如果是數(shù)字,我們可以直接比較,但如果是字符串或者兩個(gè)dict呢?直接比較數(shù)學(xué)上的大小是沒(méi)有意義的,因此,比較的過(guò)程必須通過(guò)函數(shù)抽象出來(lái)。
廖雪峰Python教程筆記(五)_第10張圖片
此外,sorted()函數(shù)也是一個(gè)高階函數(shù),它還可以接收一個(gè)key函數(shù)來(lái)實(shí)現(xiàn)自定義的排序,例如按絕對(duì)值大小排序:
在這里插入圖片描述
key指定的函數(shù)將作用于list的每一個(gè)元素上,并根據(jù)key函數(shù)返回的結(jié)果進(jìn)行排序。對(duì)比原始的list和經(jīng)過(guò)key=abs處理過(guò)的list:
廖雪峰Python教程筆記(五)_第11張圖片
字符串排序的例子:
在這里插入圖片描述
默認(rèn)情況下,對(duì)字符串排序,是按照ASCII的大小比較的,由于’Z’ < ‘a(chǎn)’,結(jié)果,大寫字母Z會(huì)排在小寫字母a的前面。

用sorted()排序的關(guān)鍵在于實(shí)現(xiàn)一個(gè)映射函數(shù)。

返回函數(shù):

函數(shù)作為返回值:高階函數(shù)除了可以接受函數(shù)作為參數(shù)外,還可以把函數(shù)作為結(jié)果值返回。
實(shí)現(xiàn)一個(gè)可變參數(shù)的求和
廖雪峰Python教程筆記(五)_第12張圖片
但是,如果不需要立刻求和,而是在后面的代碼中,根據(jù)需要再計(jì)算怎么辦?可以不返回求和的結(jié)果,而是返回求和的函數(shù):
廖雪峰Python教程筆記(五)_第13張圖片
當(dāng)我們調(diào)用lazy_sum()時(shí),返回的并不是求和結(jié)果,而是求和函數(shù):
在這里插入圖片描述
調(diào)用函數(shù)f時(shí),才真正計(jì)算求和的結(jié)果:
在這里插入圖片描述

閉包
注意到返回的函數(shù)在其定義內(nèi)部引用了局部變量args,所以,當(dāng)一個(gè)函數(shù)返回了一個(gè)函數(shù)后,其內(nèi)部的局部變量還被新函數(shù)引用,所以,閉包用起來(lái)簡(jiǎn)單,實(shí)現(xiàn)起來(lái)可不容易。

匿名函數(shù)

當(dāng)我們?cè)趥魅牒瘮?shù)時(shí),有些時(shí)候,不需要顯式地定義函數(shù),直接傳入匿名函數(shù)更方便。
在這里插入圖片描述
通過(guò)對(duì)比可以看出,匿名函數(shù)lambda x: x * x實(shí)際上就是:
在這里插入圖片描述
關(guān)鍵字lambda表示匿名函數(shù),冒號(hào)前面的x表示函數(shù)參數(shù)。
匿名函數(shù)有個(gè)限制,就是只能有一個(gè)表達(dá)式,不用寫return,返回值就是該表達(dá)式的結(jié)果。

用匿名函數(shù)有個(gè)好處,因?yàn)楹瘮?shù)沒(méi)有名字,不必?fù)?dān)心函數(shù)名沖突。此外,匿名函數(shù)也是一個(gè)函數(shù)對(duì)象,也可以把匿名函數(shù)賦值給一個(gè)變量,再利用變量來(lái)調(diào)用該函數(shù)

裝飾器

由于函數(shù)也是一個(gè)對(duì)象,而且函數(shù)對(duì)象可以被賦值給變量,所以,通過(guò)變量也能調(diào)用該函數(shù)。
廖雪峰Python教程筆記(五)_第14張圖片
函數(shù)對(duì)象有一個(gè)__name__屬性,可以拿到函數(shù)的名字:
廖雪峰Python教程筆記(五)_第15張圖片

現(xiàn)在,假設(shè)我們要增強(qiáng)now()函數(shù)的功能,比如,在函數(shù)調(diào)用前后自動(dòng)打印日志,但又不希望修改now()函數(shù)的定義,這種在代碼運(yùn)行期間動(dòng)態(tài)增加功能的方式,稱之為“裝飾器”(Decorator)。

本質(zhì)上,decorator就是一個(gè)返回函數(shù)的高階函數(shù)。所以,我們要定義一個(gè)能打印日志的decorator,可以定義如下:
廖雪峰Python教程筆記(五)_第16張圖片
觀察上面的log,因?yàn)樗且粋€(gè)decorator,所以接受一個(gè)函數(shù)作為參數(shù),并返回一個(gè)函數(shù)。我們要借助Python的@語(yǔ)法,把decorator置于函數(shù)的定義處:
在這里插入圖片描述
調(diào)用now()函數(shù),不僅會(huì)運(yùn)行now()函數(shù)本身,還會(huì)在運(yùn)行now()函數(shù)前打印一行日志:
在這里插入圖片描述
把@log放到now()函數(shù)的定義處,相當(dāng)于執(zhí)行了語(yǔ)句:
在這里插入圖片描述
由于log()是一個(gè)decorator,返回一個(gè)函數(shù),所以,原來(lái)的now()函數(shù)仍然存在,只是現(xiàn)在同名的now變量指向了新的函數(shù),于是調(diào)用now()將執(zhí)行新函數(shù),即在log()函數(shù)中返回的wrapper()函數(shù)。

偏函數(shù)

Python的functools模塊提供了很多有用的功能,其中一個(gè)就是偏函數(shù)(Partial function)。要注意,這里的偏函數(shù)和數(shù)學(xué)意義上的偏函數(shù)不一樣。

int()函數(shù)還提供額外的base參數(shù),默認(rèn)值為10。如果傳入base參數(shù),就可以做N進(jìn)制的轉(zhuǎn)換:
廖雪峰Python教程筆記(五)_第17張圖片
假設(shè)要轉(zhuǎn)換大量的二進(jìn)制字符串,每次都傳入int(x, base=2)非常麻煩,于是,我們想到,可以定義一個(gè)int2()的函數(shù),默認(rèn)把base=2傳進(jìn)去:
在這里插入圖片描述
這樣,我們轉(zhuǎn)換二進(jìn)制就非常方便了:
在這里插入圖片描述
functools.partial就是幫助我們創(chuàng)建一個(gè)偏函數(shù)的,不需要我們自己定義int2(),可以直接使用下面的代碼創(chuàng)建一個(gè)新的函數(shù)int2:
廖雪峰Python教程筆記(五)_第18張圖片
所以,簡(jiǎn)單總結(jié)functools.partial的作用就是,把一個(gè)函數(shù)的某些參數(shù)給固定住(也就是設(shè)置默認(rèn)值),返回一個(gè)新的函數(shù),調(diào)用這個(gè)新函數(shù)會(huì)更簡(jiǎn)單。

注意到上面的新的int2函數(shù),僅僅是把base參數(shù)重新設(shè)定默認(rèn)值為2,但也可以在函數(shù)調(diào)用時(shí)傳入其他值:
在這里插入圖片描述
最后,創(chuàng)建偏函數(shù)時(shí),實(shí)際上可以接收函數(shù)對(duì)象、*args和**kw這3個(gè)參數(shù),當(dāng)傳入:
在這里插入圖片描述
實(shí)際上固定了int()函數(shù)的關(guān)鍵字參數(shù)base,也就是:
在這里插入圖片描述
在這里插入圖片描述
當(dāng)傳入:
在這里插入圖片描述
廖雪峰Python教程筆記(五)_第19張圖片


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論