Python学习笔记:返回函数
前言
最近在學(xué)習(xí)深度學(xué)習(xí),已經(jīng)跑出了幾個(gè)模型,但Pyhton的基礎(chǔ)不夠扎實(shí),因此,開始補(bǔ)習(xí)Python了,大家都推薦廖雪峰的課程,因此,開始了學(xué)習(xí),但光學(xué)有沒有用,還要和大家討論一下,因此,寫下這些帖子,廖雪峰的課程連接在這里:廖雪峰
Python的相關(guān)介紹,以及它的歷史故事和運(yùn)行機(jī)制,可以參見這篇:python介紹
Python的安裝可以參見這篇:Python安裝
Python的運(yùn)行模式以及輸入輸出可以參見這篇:Python IO
Python的基礎(chǔ)概念介紹,可以參見這篇:Python 基礎(chǔ)
Python字符串和編碼的介紹,可以參見這篇:Python字符串與編碼
Python基本數(shù)據(jù)結(jié)構(gòu):list和tuple介紹,可以參見這篇:Python list和tuple
Python控制語(yǔ)句介紹:ifelse,可以參見這篇:Python 條件判斷
Python控制語(yǔ)句介紹:循環(huán)實(shí)現(xiàn),可以參見這篇:Python循環(huán)語(yǔ)句
Python數(shù)據(jù)結(jié)構(gòu):dict和set介紹Python數(shù)據(jù)結(jié)構(gòu)dict和set
Python函數(shù)相關(guān):Python函數(shù)
Python高階特性:Python高級(jí)特性
Python高階函數(shù):Python高階函數(shù)
目錄:
- 前言
- 偏函數(shù)
- 小結(jié)
- 返回函數(shù)
- 閉包
- 小結(jié)
- 練習(xí)
偏函數(shù)
Python的functools模塊提供了很多有用的功能,其中一個(gè)就是偏函數(shù)(Partial function)。要注意,這里的偏函數(shù)和數(shù)學(xué)意義上的偏函數(shù)不一樣。
在介紹函數(shù)參數(shù)的時(shí)候,我們講到,通過設(shè)定參數(shù)的默認(rèn)值,可以降低函數(shù)調(diào)用的難度。而偏函數(shù)也可以做到這一點(diǎn)。舉例如下:
int()函數(shù)可以把字符串轉(zhuǎn)換為整數(shù),當(dāng)僅傳入字符串時(shí),int()函數(shù)默認(rèn)按十進(jìn)制轉(zhuǎn)換:
>>> int('12345') 12345但int()函數(shù)還提供額外的base參數(shù),默認(rèn)值為10。如果傳入base參數(shù),就可以做N進(jìn)制的轉(zhuǎn)換:
>>> int('12345', base=8) 5349 >>> int('12345', 16) 74565假設(shè)要轉(zhuǎn)換大量的二進(jìn)制字符串,每次都傳入int(x, base=2)非常麻煩,于是,我們想到,可以定義一個(gè)int2()的函數(shù),默認(rèn)把base=2傳進(jìn)去:
def int2(x, base=2):return int(x, base)這樣,我們轉(zhuǎn)換二進(jìn)制就非常方便了:
>>> int2('1000000') 64 >>> int2('1010101') 85functools.partial就是幫助我們創(chuàng)建一個(gè)偏函數(shù)的,不需要我們自己定義int2(),可以直接使用下面的代碼創(chuàng)建一個(gè)新的函數(shù)int2:
>>> import functools >>> int2 = functools.partial(int, base=2) >>> int2('1000000') 64 >>> int2('1010101') 85所以,簡(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)傳入:
int2 = functools.partial(int, base=2)實(shí)際上固定了int()函數(shù)的關(guān)鍵字參數(shù)base,也就是:
int2('10010')相當(dāng)于:kw = { 'base': 2 } int('10010', **kw)當(dāng)傳入:max2 = functools.partial(max, 10)實(shí)際上會(huì)把10作為*args的一部分自動(dòng)加到左邊,也就是:max2(5, 6, 7)相當(dāng)于:
args = (10, 5, 6, 7) max(*args)結(jié)果為10。
小結(jié)
當(dāng)函數(shù)的參數(shù)個(gè)數(shù)太多,需要簡(jiǎn)化時(shí),使用functools.partial可以創(chuàng)建一個(gè)新的函數(shù),這個(gè)新函數(shù)可以固定住原函數(shù)的部分參數(shù),從而在調(diào)用時(shí)更簡(jiǎn)單。
返回函數(shù)
函數(shù)作為返回值
高階函數(shù)除了可以接受函數(shù)作為參數(shù)外,還可以把函數(shù)作為結(jié)果值返回。
我們來實(shí)現(xiàn)一個(gè)可變參數(shù)的求和。通常情況下,求和的函數(shù)是這樣定義的:
但是,如果不需要立刻求和,而是在后面的代碼中,根據(jù)需要再計(jì)算怎么辦?可以不返回求和的結(jié)果,而是返回求和的函數(shù):
def lazy_sum(*args):def sum():ax = 0for n in args:ax = ax + nreturn axreturn sum當(dāng)我們調(diào)用lazy_sum()時(shí),返回的并不是求和結(jié)果,而是求和函數(shù):
>>> f = lazy_sum(1, 3, 5, 7, 9) >>> f <function lazy_sum.<locals>.sum at 0x101c6ed90>調(diào)用函數(shù)f時(shí),才真正計(jì)算求和的結(jié)果:
>>> f() 25在這個(gè)例子中,我們?cè)诤瘮?shù)lazy_sum中又定義了函數(shù)sum,并且,內(nèi)部函數(shù)sum可以引用外部函數(shù)lazy_sum的參數(shù)和局部變量,當(dāng)lazy_sum返回函數(shù)sum時(shí),相關(guān)參數(shù)和變量都保存在返回的函數(shù)中,這種稱為“閉包(Closure)”的程序結(jié)構(gòu)擁有極大的威力。
請(qǐng)?jiān)僮⒁庖稽c(diǎn),當(dāng)我們調(diào)用lazy_sum()時(shí),每次調(diào)用都會(huì)返回一個(gè)新的函數(shù),即使傳入相同的參數(shù):
>>> f1 = lazy_sum(1, 3, 5, 7, 9) >>> f2 = lazy_sum(1, 3, 5, 7, 9) >>> f1==f2 Falsef1()和f2()的調(diào)用結(jié)果互不影響。
閉包
注意到返回的函數(shù)在其定義內(nèi)部引用了局部變量args,所以,當(dāng)一個(gè)函數(shù)返回了一個(gè)函數(shù)后,其內(nèi)部的局部變量還被新函數(shù)引用,所以,閉包用起來簡(jiǎn)單,實(shí)現(xiàn)起來可不容易。
另一個(gè)需要注意的問題是,返回的函數(shù)并沒有立刻執(zhí)行,而是直到調(diào)用了f()才執(zhí)行。我們來看一個(gè)例子:
在上面的例子中,每次循環(huán),都創(chuàng)建了一個(gè)新的函數(shù),然后,把創(chuàng)建的3個(gè)函數(shù)都返回了。
你可能認(rèn)為調(diào)用f1(),f2()和f3()結(jié)果應(yīng)該是1,4,9,但實(shí)際結(jié)果是:
>>> f1() 9 >>> f2() 9 >>> f3() 9全部都是9!原因就在于返回的函數(shù)引用了變量i,但它并非立刻執(zhí)行。等到3個(gè)函數(shù)都返回時(shí),它們所引用的變量i已經(jīng)變成了3,因此最終結(jié)果為9。
返回閉包時(shí)牢記一點(diǎn):返回函數(shù)不要引用任何循環(huán)變量,或者后續(xù)會(huì)發(fā)生變化的變量。
如果一定要引用循環(huán)變量怎么辦?方法是再創(chuàng)建一個(gè)函數(shù),用該函數(shù)的參數(shù)綁定循環(huán)變量當(dāng)前的值,無論該循環(huán)變量后續(xù)如何更改,已綁定到函數(shù)參數(shù)的值不變:
def count():def f(j):def g():return j*jreturn gfs = []for i in range(1, 4):fs.append(f(i)) # f(i)立刻被執(zhí)行,因此i的當(dāng)前值被傳入f()return fs再看看結(jié)果:
>>> f1, f2, f3 = count() >>> f1() 1 >>> f2() 4 >>> f3() 9缺點(diǎn)是代碼較長(zhǎng),可利用lambda函數(shù)縮短代碼。
小結(jié)
一個(gè)函數(shù)可以返回一個(gè)計(jì)算結(jié)果,也可以返回一個(gè)函數(shù)。
返回一個(gè)函數(shù)時(shí),牢記該函數(shù)并未執(zhí)行,返回函數(shù)中不要引用任何可能會(huì)變化的變量。
練習(xí)
生成一個(gè)計(jì)數(shù)器:
def createCounter():i=[1]def count():def c(j):i[0]=i[0]+1return jreturn c(i[0])return count總結(jié)
以上是生活随笔為你收集整理的Python学习笔记:返回函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安装redis并开启_如何安装Redis
- 下一篇: Python学习笔记:装饰器