91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python中最神秘的魔法函數是什么

發布時間:2021-12-23 16:30:10 來源:億速云 閱讀:171 作者:iii 欄目:開發技術

這篇文章主要介紹“Python中最神秘的魔法函數是什么”,在日常操作中,相信很多人在Python中最神秘的魔法函數是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Python中最神秘的魔法函數是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

本文主要關注的問題有:(1) missing()到底是何方神圣?(2) missing()有什么特別之處?擅長“大變活人”魔術?

(3) missing()是否真的是上述發現的例外?如果是的話,為什么會有這種特例?

1、有點價值的missing()

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

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

Python中最神秘的魔法函數是什么

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

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

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

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

Python中最神秘的魔法函數是什么

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

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

原因是 defaultdict 在繼承了內置類型 dict 之后,還定義了一個 missing() 方法,當 getitem取不存在的值時,它就會調用入參中傳入的工廠函數(上例是調用 list(),創建空列表)。

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

Python中最神秘的魔法函數是什么

簡而言之,missing()的主要作用就是由getitem在缺失 key 時調用,從而避免出現 KeyError。

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

Python中最神秘的魔法函數是什么

2、神出鬼沒的missing()

由上可知,missing()在getitem()取不到值時會被調用,但是,我不經意間還發現了一個細節:getitem()在取不到值時,并不一定會調用missing()。

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

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

使用 dir() 查看,發現確實不存在該屬性:

Python中最神秘的魔法函數是什么

如果從 dict 的父類即 object 中查看,也會發現同樣的結果。

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

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

Python中最神秘的魔法函數是什么

出處:3. Data model — Python 3.10.1 documentationmissing#object.missing

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

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

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

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

Python中最神秘的魔法函數是什么

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

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

3、被施魔法的missing()

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

我發現原生的魔術方法間相互獨立,它們在 C 語言界面可能有相同的核心邏輯,但是在 Python 語言界面,卻并不存在著調用關系:

Python中最神秘的魔法函數是什么

魔術方法的這種“老死不相往來”的表現,違背了一般的代碼復用原則,也是導致內置類型的子類會出現某些奇怪表現的原因。

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

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

missing() 是魔術方法的“二等公民”,它沒有獨立的調用入口,只能被動地由 getitem() 調用,即missing() 依賴于getitem()。

不同于那些“一等公民”,例如 init()、enter()、len()、eq() 等等,它們要么是在對象生命周期或執行過程的某個節點被觸發,要么由某個內置函數或操作符觸發,這些都是相對獨立的事件,無所依賴。

missing() 依賴于getitem(),才能實現方法調用;而 getitem() 也要依賴 missing(),才能實現完整功能。

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

Python中最神秘的魔法函數是什么

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

到此,關于“Python中最神秘的魔法函數是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

兖州市| 祁连县| 汤原县| 吴川市| 织金县| 荥阳市| 陈巴尔虎旗| 广河县| 霍山县| 宣武区| 扶绥县| 和顺县| 邓州市| 苗栗县| 浦东新区| 玉屏| 衡水市| 太湖县| 张家界市| 共和县| 宁城县| 长垣县| 湟中县| 定边县| 临泽县| 三河市| 宁蒗| 五家渠市| 宽甸| 梁河县| 德保县| 南宁市| 长寿区| 若尔盖县| 灵川县| 昭平县| 五常市| 互助| 龙口市| 临沂市| 原平市|