摘要:變量查找規(guī)則在中一個(gè)變量的查找順序是局部環(huán)境,閉包,全局,內(nèi)建閉包引用了自由變量的函數(shù)。閉包的作用閉包的最大特點(diǎn)是可以將父函數(shù)的變量與內(nèi)部函數(shù)綁定,并返回綁定變量后的函數(shù),此時(shí)即便生成閉包的環(huán)境父函數(shù)已經(jīng)釋放,閉包仍然存在。
導(dǎo)語:本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之函數(shù)篇的重點(diǎn)知識(shí)及個(gè)人心得,打算入門Python的朋友們可以來一起學(xué)習(xí)并交流。
本文重點(diǎn):
1、掌握裝飾器的本質(zhì)、功能和特點(diǎn);一、裝飾器基礎(chǔ)知識(shí)
2、了解閉包的概念以及Python變量調(diào)用規(guī)則;
3、了解并學(xué)會(huì)使用標(biāo)準(zhǔn)庫中重要的裝飾器;
4、掌握參數(shù)化裝飾器的意義和代碼實(shí)現(xiàn)方式。
裝飾器功能(decorator):將被裝飾的函數(shù)當(dāng)作參數(shù)傳遞給與裝飾器對(duì)應(yīng)的函數(shù)(名稱相同的函數(shù)),并返回包裝后的被裝飾的函數(shù)。
裝飾器本質(zhì):是一個(gè)返回函數(shù)的高階函數(shù)。
裝飾器特點(diǎn):
1、多數(shù)裝飾器會(huì)把被裝飾的函數(shù)替換成其他函數(shù)
2、函數(shù)裝飾器在導(dǎo)入模塊時(shí)立即執(zhí)行,而被裝飾的函數(shù)只在明確調(diào)用時(shí)執(zhí)行。
裝飾器有時(shí)采用嵌套函數(shù)表示的原因(個(gè)人理解):
一些裝飾器的裝飾功能只有在被裝飾函數(shù)被調(diào)用時(shí)方可觸發(fā),因此需要用嵌套函數(shù)的形式來編寫。
自由變量(free variable):指未在本地作用域綁定的變量,介于局部變量和全局變量之間。
變量查找規(guī)則:在python中, 一個(gè)變量的查找順序是 LEGB (L:Local 局部環(huán)境,E:Enclosing 閉包,G:Global 全局,B:Built-in 內(nèi)建).
閉包:引用了自由變量的函數(shù)。
閉包的作用:
閉包的最大特點(diǎn)是可以將父函數(shù)的變量與內(nèi)部函數(shù)綁定,并返回綁定變量后的函數(shù),此時(shí)即便生成閉包的環(huán)境(父函數(shù))已經(jīng)釋放,閉包仍然存在。
這個(gè)過程很像類(父函數(shù))生成實(shí)例(閉包),不同的是父函數(shù)只在調(diào)用時(shí)執(zhí)行,執(zhí)行完畢后其環(huán)境就會(huì)釋放,而類則在文件執(zhí)行時(shí)創(chuàng)建,一般程序執(zhí)行完畢后作用域才釋放。
因此對(duì)一些需要重用的功能且不足以定義為類的行為,使用閉包會(huì)比使用類占用更少的資源,且更輕巧靈活。
nonlocal聲明:可以將局部變量聲明為自由變量。
eg:計(jì)算移動(dòng)平均值的高階函數(shù):
def averager(): sum=0 n=0 def avg(i): nonlocal sum,n sum+=i n+=1 return print(sum/n) return avg a=averager() a(3) a(5) a(7)
輸出分別是3,4,5
三、裝飾器進(jìn)階使用 1.標(biāo)準(zhǔn)庫中的裝飾器Python內(nèi)置了三個(gè)用于裝飾方法的函數(shù):property,classmethod和staticmethod
三個(gè)重要的內(nèi)置裝飾器:
functools.wraps:
(1)協(xié)助構(gòu)建行為良好的裝飾器。
(2)可以把被裝飾對(duì)象的相關(guān)屬性復(fù)制到裝飾器中,默認(rèn)有 __module__、__name__、__doc__。
(3)個(gè)人理解,裝飾器在實(shí)現(xiàn)裝飾的過程中意見把被裝飾函數(shù)替換了。此時(shí)你想調(diào)用被裝飾函數(shù)的__doc__和__name__會(huì)發(fā)現(xiàn)是none,此時(shí)通過functools.wraps就可以在裝飾時(shí)把相關(guān)屬性復(fù)制過來使用,避免這個(gè)問題發(fā)生。
functools.lru_cache
(1)實(shí)現(xiàn)備忘功能,即緩存,避免發(fā)生重復(fù)調(diào)用來提高效率。
(2)注意調(diào)用時(shí)必須帶括號(hào),因?yàn)榇搜b飾器包含maxsize和typed兩個(gè)參數(shù),帶括號(hào)表示使用默認(rèn)參數(shù)。否則 functools.lru_cache不清楚該如何執(zhí)行。
functools.singledispatch
為函數(shù)提供重載功能。被其裝飾的函數(shù)會(huì)成為泛函數(shù)(generic function):根據(jù)第一個(gè)參數(shù)的類型,用不同的方式執(zhí)行相同操作的一組函數(shù)。
以functools.lru_cache為例實(shí)現(xiàn)斐波那契函數(shù)的計(jì)時(shí)裝飾器:.
import time import functools def clock(func): @functools.lru_cache()#減少重復(fù)自引用,避免重復(fù)計(jì)算 def clocked(arg): t0=time.perf_counter() func(arg) result=func(arg) t1=time.perf_counter() processtime=t1-t0 name=func.__name__ print("[{0:.8f}] {1}({2})={3}".format(processtime,name,arg,result)) return result#非常重要,否則破壞原fibs函數(shù)導(dǎo)致無法遞歸調(diào)用。 return clocked @clock def fibs(n): if n<2: return 1 else: return fibs(n-1)+fibs(n-2) fibs(6)#輸出82.疊放裝飾器
如同函數(shù)可以嵌套使用,裝飾器亦可以疊放起來裝飾同一對(duì)象。語法如下:
@d1
@d2
def f1():
pass
上述裝飾操作等價(jià)于d1(d2(f)),故易知疊放在上端的裝飾器靠后執(zhí)行。
普通裝飾器的進(jìn)階版,通過參數(shù)接口可以更方便的定制我們需要的裝飾器,適應(yīng)需求變化。
代碼實(shí)現(xiàn)較普通裝飾器多嵌套一層函數(shù),用來傳遞用戶輸入的參數(shù)。以計(jì)時(shí)器舉例形式如下:
import time DEFAULT_FMT = "[{elapsed:0.8f}s] {name}({args}) -> {result}" def clock(fmt=DEFAULT_FMT): #三層函數(shù)來實(shí)現(xiàn) def decorate(func): def clocked(*_args): t0 = time.time() _result = func(*_args) elapsed = time.time() - t0 name = func.__name__ args = ", ".join(repr(arg) for arg in _args) result = repr(_result) print(fmt.format(**locals())) return _result return clocked return decorate if __name__ == "__main__": @clock() def snooze(seconds): time.sleep(seconds) for i in range(3): snooze(.123)
輸出:
[0.12480044s] snooze(0.123) -> None [0.13660240s] snooze(0.123) -> None [0.12480044s] snooze(0.123) -> None4.類裝飾器
上邊實(shí)現(xiàn)參數(shù)化裝飾器的代碼由于包含三重嵌套略顯復(fù)雜, 事實(shí)上復(fù)雜的裝飾器用 class 實(shí)現(xiàn)更方便。通過 __call__ 方法即可改寫參數(shù)化裝飾器。具體實(shí)現(xiàn)留作勤勞的你去課后思考,感興趣的可以與我私信交流。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/41475.html
摘要:初步認(rèn)識(shí)裝飾器函數(shù)裝飾器用于在源代碼中標(biāo)記函數(shù),以某種方式增強(qiáng)函數(shù)的行為。函數(shù)裝飾器在導(dǎo)入模塊時(shí)立即執(zhí)行,而被裝飾的函數(shù)只在明確調(diào)用時(shí)運(yùn)行。只有涉及嵌套函數(shù)時(shí)才有閉包問題。如果想保留函數(shù)原本的屬性,可以使用標(biāo)準(zhǔn)庫中的裝飾器。 《流暢的Python》筆記本篇將從最簡單的裝飾器開始,逐漸深入到閉包的概念,然后實(shí)現(xiàn)參數(shù)化裝飾器,最后介紹標(biāo)準(zhǔn)庫中常用的裝飾器。 1. 初步認(rèn)識(shí)裝飾器 函數(shù)裝飾...
摘要:函數(shù)裝飾器和閉包嚴(yán)格來說,裝飾器只是語法糖。何時(shí)執(zhí)行裝飾器它們?cè)诒谎b飾的函數(shù)定義之后立即運(yùn)行。裝飾器突出了被裝飾的函數(shù)的作用,還便于臨時(shí)禁用某個(gè)促銷策略只需把裝飾器注釋掉。 函數(shù)裝飾器和閉包 嚴(yán)格來說,裝飾器只是語法糖。如前所示,裝飾器可以像常規(guī)的可調(diào)用對(duì)象那樣調(diào)用,其參數(shù)是另一個(gè)函數(shù)。有時(shí),這樣做更方便,尤其是做元編程(在運(yùn)行時(shí)改變程序的行為)時(shí)。 Python何時(shí)執(zhí)行裝飾器 它們?cè)?..
摘要:迭代器迭代是訪問集合元素的一種方式。迭代器是一個(gè)可以記住遍歷的位置的對(duì)象,迭代器對(duì)象從集合的第一個(gè)元素開始訪問,直到所有的元素被訪問完結(jié)束,迭代器只往前不會(huì)往后退。生成器特點(diǎn)保存了一套生成數(shù)值的算法。 迭代器 迭代是訪問集合元素的一種方式。迭代器是一個(gè)可以記住遍歷的位置的對(duì)象,迭代器對(duì)象從集合的第一個(gè)元素開始訪問,直到所有的元素被訪問完結(jié)束,迭代器只往前不會(huì)往后退。 可迭代對(duì)象 以直接...
摘要:重寫內(nèi)建名字空間中的函數(shù)閉包閉包是詞法閉包的簡稱。另一種說法認(rèn)為閉包是由函數(shù)和與其相關(guān)的引用環(huán)境組合而成的實(shí)體。 Python 中的 Decorator(裝飾器) 是對(duì)一個(gè)函數(shù)或者方法的封裝,從而使其可以完成一些與自身功能無關(guān)的工作。 預(yù)備知識(shí) 一切皆對(duì)象 在 Python 中,所有的一切都被視為對(duì)象,任何的變量、函數(shù)、類等都是 object 的子類。因此除了變量之外,函數(shù)和類等也可以...
閱讀 3143·2021-10-13 09:39
閱讀 2760·2021-09-27 13:34
閱讀 2115·2019-08-30 15:55
閱讀 3306·2019-08-30 15:43
閱讀 3711·2019-08-30 11:16
閱讀 1833·2019-08-26 18:28
閱讀 1404·2019-08-26 13:56
閱讀 1006·2019-08-26 13:35