Python編程:核心協(xié)議知多少之函協(xié)議數(shù)與上下文管協(xié)議
前言
在前面的幾篇內(nèi)容中,對(duì)Python的幾個(gè)核心,對(duì)象協(xié)議、數(shù)字協(xié)議、比較協(xié)議、轉(zhuǎn)換協(xié)議、容器協(xié)議、迭代協(xié)議以及屬性協(xié)議等結(jié)合示例性代碼做了扼要介紹。
本篇內(nèi)容介紹函數(shù)協(xié)議(Function Protocol)以及上下文管理協(xié)議(Context Manager Protocol)。
函數(shù)協(xié)議
我們知道Python是動(dòng)態(tài)語言,是由解釋器來讀取代碼進(jìn)行解釋執(zhí)行的,這其中就涉及函數(shù)(在類的上下文語境中,所屬對(duì)象的函數(shù)中稱之為方法)的解釋執(zhí)行,所以必須遵循一定的協(xié)議規(guī)則,否則就亂套了。
在對(duì)象中,對(duì)象可以通過提供__call__()方法來模擬函數(shù)。假設(shè)一個(gè)對(duì)象x提供了這個(gè)方法,它可以像函數(shù)一樣被調(diào)用。也就是說,x(__arg1,arg2,…)實(shí)際是調(diào)用了x.__call__ (__arg1,arg2,…)。簡(jiǎn)單示例如下:
其實(shí)上述代碼的最后一行還可以寫成:xc.__call__('祖龍','中國(guó)'),結(jié)果完全一樣??烧{(diào)用對(duì)象,實(shí)際上“名稱()”可以理解為是“名稱.__call__()”的簡(jiǎn)寫。
有許多內(nèi)置類型支持函數(shù)調(diào)用。例如,類型(types)實(shí)現(xiàn)了調(diào)用__call__()來創(chuàng)建新實(shí)例。綁定(Bound)方法實(shí)現(xiàn)了__call__()來將self參數(shù)傳遞給實(shí)例方法。像functools.partial()這樣的庫函數(shù)也創(chuàng)建模擬函數(shù)的對(duì)象。
上下文管理協(xié)議
這里所謂的上下文管理協(xié)議,主要是指在一個(gè)特定范圍的代碼塊。Python使用with語句來實(shí)現(xiàn),即with語句允許在稱為上下文管理器的實(shí)例的控制下執(zhí)行一系列語句。一般語法如下:
實(shí)現(xiàn)這樣的上下文協(xié)議的,需要支持如下的特定方法:
- __enter__(self)方法:在進(jìn)入新的新上下文的位置調(diào)用此函數(shù)。返回值被放置在with語句一起列出的由as指定的變量中。
- __exit__(self,type,value,tb)方法:在離開上下文時(shí)調(diào)用。如果發(fā)生異常,type、value和tb包含異常類型、值和相關(guān)跟蹤信息。
在執(zhí)行with語句時(shí)調(diào)用__enter__()方法。此方法返回的值被放入用可選的as var說明符指定的變量中。在control-flow離開與with語句相關(guān)聯(lián)的語句塊時(shí),__exit__()方法就會(huì)被調(diào)用。作為參數(shù),__exit__()接收當(dāng)前異常類型、值,并在引發(fā)異常時(shí)進(jìn)行回溯。如果不處理任何錯(cuò)誤,則將所有三個(gè)值都設(shè)置為None。__exit__()方法應(yīng)該返回True或False,以指示是否處理了引發(fā)的異常。如果返回True,則清除任何掛起的異常,程序繼續(xù)正常執(zhí)行with塊后的第一個(gè)語句。
上下文管理接口的主要用途是允許對(duì)涉及系統(tǒng)狀態(tài)的對(duì)象進(jìn)行簡(jiǎn)化的資源控制,例如打開的文件、網(wǎng)絡(luò)連接和鎖等。通過實(shí)現(xiàn)這個(gè)接口,當(dāng)執(zhí)行離開使用對(duì)象的上下文時(shí),對(duì)象可以安全地清理資源了。
小結(jié)
本篇就寫這些了,簡(jiǎn)單扼要地介紹了函數(shù)協(xié)議(直接調(diào)用對(duì)象作為函數(shù))實(shí)現(xiàn)、以及上下文的協(xié)議實(shí)現(xiàn)。