久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      Python魔法函數(shù)學(xué)習之__missing__

      本篇文章給大家?guī)砹岁P(guān)于python的相關(guān)知識,其中主要介紹了“__missing__()”函數(shù)的相關(guān)問題,下面我們就一起來看一下這個魔法函數(shù),希望對大家有幫助。

      Python魔法函數(shù)學(xué)習之__missing__

      推薦學(xué)習:python學(xué)習教程

      1、有點價值的__missing__()

      從普通的字典中取值時,可能會出現(xiàn) key 不存在的情況:

      dd = {'name':'PythonCat'} dd.get('age')        # 結(jié)果:None dd.get('age', 18)    # 結(jié)果:18 dd['age']            # 報錯 KeyError dd.__getitem__('age')  # 等同于 dd['age']

      Python魔法函數(shù)學(xué)習之__missing__

      對于 get() 方法,它是有返回值的,而且可以傳入第二個參數(shù),作為 key 不存在時的返回內(nèi)容,因此還可以接受。但是,另外兩種寫法都會報錯。

      為了解決后兩種寫法的問題,就可以用到 __missing__() 魔術(shù)方法。

      現(xiàn)在,假設(shè)我們有一個這樣的訴求:從字典中取某個 key 對應(yīng)的 value,如果有值則返回值,如果沒有值則插入 key,并且給它一個默認值(例如一個空列表)。

      如果用原生的 dict,并不太好實現(xiàn),但是,Python 提供了一個非常好用的擴展類collections.defaultdict

      Python魔法函數(shù)學(xué)習之__missing__

      如圖所示,當取不存在的 key 時,沒有再報 KeyError,而是默認存入到字典中。

      為什么 defaultdict 可以做到這一點呢?

      原因是 defaultdict 在繼承了內(nèi)置類型 dict 之后,還定義了一個 __missing__() 方法,當 __getitem__取不存在的值時,它就會調(diào)用入?yún)⒅袀魅氲墓S函數(shù)(上例是調(diào)用 list(),創(chuàng)建空列表)。

      作為最典型的示例,defaultdict 在文檔注釋中寫到:

      Python魔法函數(shù)學(xué)習之__missing__

      簡而言之,__missing__()的主要作用就是由__getitem__在缺失 key 時調(diào)用,從而避免出現(xiàn) KeyError。

      另外一個典型的使用例子是collections.Counter,它也是 dict 的子類,在取未被統(tǒng)計的 key 時,返回計數(shù) 0:

      Python魔法函數(shù)學(xué)習之__missing__

      2、神出鬼沒的__missing__()

      由上可知,__missing__()在__getitem__()取不到值時會被調(diào)用,但是,我不經(jīng)意間還發(fā)現(xiàn)了一個細節(jié):__getitem__()在取不到值時,并不一定會調(diào)用__missing__()。

      這是因為它并非內(nèi)置類型的必要屬性,并沒有在字典基類中被預(yù)先定義。

      如果你直接從 dict 類型中取該屬性值,會報屬性不存在:AttributeError: type object 'object' has no attribute '__missing__'。

      使用 dir() 查看,發(fā)現(xiàn)確實不存在該屬性:

      Python魔法函數(shù)學(xué)習之__missing__

      如果從 dict 的父類即 object 中查看,也會發(fā)現(xiàn)同樣的結(jié)果。

      這是怎么回事呢?為什么在 dict 和 object 中都沒有__missing__屬性呢?

      然而,查閱最新的官方文檔,object 中分明包含這個屬性:

      Python魔法函數(shù)學(xué)習之__missing__

      出處:https://docs.python.org/3/reference/datamodel.html?highlight=__missing__#object.__missing__

      也就是說,理論上 object 類中會預(yù)定義__missing__,其文檔證明了這一點,然而實際上它并沒有被定義!文檔與現(xiàn)實出現(xiàn)了偏差!

      如此一來,當 dict 的子類(例如 defaultdict 和 Counter)在定義__missing__ 時,這個魔術(shù)方法事實上只屬于該子類,也就是說,它是一個誕生于子類中的魔術(shù)方法!

      據(jù)此,我有一個不成熟的猜想:__getitem__()會判斷當前對象是否是 dict 的子類,且是否擁有__missing__(),然后才會去調(diào)用它(如果父類中也有該方法,則不會先作判斷,而是直接就調(diào)用了)。

      我在交流群里說出了這個猜想,有同學(xué)很快在 CPython 源碼中找到驗證:

      Python魔法函數(shù)學(xué)習之__missing__

      而這就有意思了,在內(nèi)置類型的子類上才存在的魔術(shù)方法,縱觀整個 Python 世界,恐怕再難以找出第二例。

      我突然有一個聯(lián)想:這神出鬼沒的__missing__(),就像是一個擅長玩“大變活人”的魔術(shù)師,先讓觀眾在外面透過玻璃看到他(即官方文檔),然而揭開門時,他并不在里面(即內(nèi)置類型),再變換一下道具,他又完好無損就出現(xiàn)了(即 dict 的子類)。

      3、被施魔法的__missing__()

      __missing__() 的神奇之處,除了它本身會變“魔術(shù)”之外,它還需要一股強大的“魔法”才能驅(qū)動。

      在上篇文章中,我發(fā)現(xiàn)原生的魔術(shù)方法間相互獨立,它們在 C 語言界面可能有相同的核心邏輯,但是在 Python 語言界面,卻并不存在著調(diào)用關(guān)系:

      Python魔法函數(shù)學(xué)習之__missing__

      魔術(shù)方法的這種“老死不相往來”的表現(xiàn),違背了一般的代碼復(fù)用原則,也是導(dǎo)致內(nèi)置類型的子類會出現(xiàn)某些奇怪表現(xiàn)的原因。

      官方 Python 寧肯提供新的 UserString、UserList、UserDict 子類,也不愿意復(fù)用魔術(shù)方法,唯一合理的解釋似乎是令魔術(shù)方法相互調(diào)用的代價太大。

      但是,對于特例__missing__(),Python 卻不得不妥協(xié),不得不付出這種代價!

      __missing__() 是魔術(shù)方法的“二等公民”,它沒有獨立的調(diào)用入口,只能被動地由 __getitem__() 調(diào)用,即__missing__() 依賴于__getitem__()。

      不同于那些“一等公民”,例如 __init__()、__enter__()、__len__()、__eq__() 等等,它們要么是在對象生命周期或執(zhí)行過程的某個節(jié)點被觸發(fā),要么由某個內(nèi)置函數(shù)或操作符觸發(fā),這些都是相對獨立的事件,無所依賴。

      __missing__() 依賴于__getitem__(),才能實現(xiàn)方法調(diào)用;而 __getitem__() 也要依賴 __missing__(),才能實現(xiàn)完整功能。

      為了實現(xiàn)這一點,__getitem__()在解釋器代碼中開了個后門,從 C 語言界面折返回 Python 界面,去調(diào)用那個名為“__missing__”的特定方法。

      Python魔法函數(shù)學(xué)習之__missing__

      而這就是真正的“魔法”了,目前為止,__missing__()似乎是唯一一個享受了此等待遇的魔術(shù)方法!

      4、小結(jié)

      Python 的字典提供了兩種取值的內(nèi)置方法,即__getitem__() 和 get(),當取值不存在時,它們的處理策略是不一樣的:前者會報錯KeyError,而后者會返回 None。

      為什么 Python 要提供兩個不同的方法呢?或者應(yīng)該問,為什么 Python 要令這兩個方法做出不一樣的處理呢?

      這可能有一個很復(fù)雜(也可能是很簡單)的解釋,本文暫不深究了。

      不過有一點是可以確定的:即原生 dict 類型簡單粗暴地拋KeyError的做法有所不足。

      為了讓字典類型有更強大的表現(xiàn)(或者說讓__getitem__()作出 get() 那樣的表現(xiàn)),Python 讓字典的子類可以定義__missing__(),供__getitem__()查找調(diào)用。

      本文梳理了__missing__()的實現(xiàn)原理,從而揭示出它并非是一個毫不起眼的存在,恰恰相反,它是唯一一個打破了魔術(shù)方法間壁壘,支持被其它魔術(shù)方法調(diào)用的特例!

      Python 為了維持魔術(shù)方法的獨立性,不惜煞費苦心地引入了 UserString、UserList、UserDict 這些派生類,但是對于 __missing__(),它卻選擇了妥協(xié)。

      推薦學(xué)習:python教程

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號