這篇文章主要介紹了關於淺談Python中重載isinstance繼承關係的問題,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下
判斷繼承關係
透過內建方法isinstance(object, classinfo) 可以判斷一個物件是否是某個類別的實例。這個關係可以是直接,間接或抽象。
實例的檢查是允許重載的,可見文件customizing-instance-and-subclass-checks 。根據PEP 3119 的描述:
The primary mechanism proposed here is to allow overloading the built-in functions isinstance() and issubclass(). The overloading works as follows: Theinstance() and issubclass(). The overloading works as follows: The call is ) first checks whether C.__instancecheck__ exists, and if so, calls C.__instancecheck__(x) instead of its normal implementation.
這段話的意思是,當調用isinstance(x , C) 進行偵測時,會優先檢查是否存在C.__instancecheck__ ,如果存在則呼叫C.__instancecheck__(x) ,傳回的結果是實例偵測的結果,預設的判斷方式就沒有了。
這種方式有助於我們來檢查鴨子類型,我用程式碼測了一下。
class Sizeable(object): def __instancecheck__(cls, instance): print("__instancecheck__ call") return hasattr(instance, "__len__") class B(object): pass b = B() print(isinstance(b, Sizeable)) # output:False
只列印了 False,且 __instancecheck__ 沒有呼叫。這是怎麼回事。
沒有執行的 __instancecheck__
可見文件寫得併不清楚,為了找出問題,我們從 isinstance 原始碼開始進行追蹤。
[abstract.c] int PyObject_IsInstance(PyObject *inst, PyObject *cls) { _Py_IDENTIFIER(__instancecheck__); PyObject *checker; /* Quick test for an exact match */ if (Py_TYPE(inst) == (PyTypeObject *)cls) return 1; .... }
Py_TYPE(inst) == (PyTypeObject *)cls 這是快速匹配的方式,等價於type(inst) is cls ,這種快速的方式來搭配成功的話,也不會去檢查__instancecheck__ 。所以文件中的優先檢查是否有 C.__instancecheck__ 有誤。繼續向下看原始碼:
/* We know what type's __instancecheck__ does. */ if (PyType_CheckExact(cls)) { return recursive_isinstance(inst, cls); }
展開巨集PyType_CheckExact :
##
[object.h] #define PyType_CheckExact(op) (Py_TYPE(op) == &PyType_Type)#也就是說cls 是由type 直接建構出來的類,則判斷語言成立。除了類別宣告裡指定 metaclass 外基本上都是由 type 直接建構的。從測試程式碼得知判斷成立,進入 recursive_isinstance。但這個函數裡面我卻找不到 __instancecheck__ 的程式碼,recursive_isinstance 的判斷邏輯大致上是:
def recursive_isinstance(inst, cls): return pyType_IsSubtype(inst, cls) def pyType_IsSubtype(a, b): for mro in a.__mro__: if mro is b: return True return False是從 __mro__ 繼承順序來判斷的。回到PyObject_IsInstance 函式往下看:
if (PyTuple_Check(cls)) { ... }#這是當instance(x, C) 第二個參數是元組的情況,裡面的處理方式是遞歸呼叫PyObject_IsInstance(inst, item) 。繼續往下看:
checker = _PyObject_LookupSpecial(cls, &PyId___instancecheck__); if (checker != NULL) { res = PyObject_CallFunctionObjArgs(checker, inst, NULL); ok = PyObject_IsTrue(res); return ok; }顯然,這邊才是獲得__instancecheck__ 的地方,為了讓檢查流程走到這裡,定義的類別要指明metaclass 。剩下就是追蹤下 _PyObject_LookupSpecial 就可以了:
[typeobject.c] PyObject * _PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid) { PyObject *res; res = _PyType_LookupId(Py_TYPE(self), attrid); // 有回调的话处理回调 // ... return res; }取的是 Py_TYPE(self) ,也就是說指定的 metaclass 裡面需要定義 __instancecheck__ 。
總結
- x 物件不能是由C 直接實例化; ##C 類別指定metaclass ;
- 指定的metaclass 類別中定義了__instancecheck__ 。
- 測試程式碼:
class MetaSizeable(type): def __instancecheck__(cls, instance): print("__instancecheck__ call") return hasattr(instance, "__len__") class Sizeable(metaclass=MetaSizeable): pass class B(object): pass b = B() print(isinstance(b, Sizeable)) # output: False print(isinstance([], Sizeable)) # output: True
#文件可能有點老舊了。本次測試的環境是Python3.6。
相關推薦:
以上是淺談Python中重載isinstance繼承關係的問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Python在web開發、數據科學、機器學習、自動化和腳本編寫等領域有廣泛應用。 1)在web開發中,Django和Flask框架簡化了開發過程。 2)數據科學和機器學習領域,NumPy、Pandas、Scikit-learn和TensorFlow庫提供了強大支持。 3)自動化和腳本編寫方面,Python適用於自動化測試和系統管理等任務。

兩小時內可以學到Python的基礎知識。 1.學習變量和數據類型,2.掌握控制結構如if語句和循環,3.了解函數的定義和使用。這些將幫助你開始編寫簡單的Python程序。

如何在10小時內教計算機小白編程基礎?如果你只有10個小時來教計算機小白一些編程知識,你會選擇教些什麼�...

使用FiddlerEverywhere進行中間人讀取時如何避免被檢測到當你使用FiddlerEverywhere...

Python3.6環境下加載Pickle文件報錯:ModuleNotFoundError:Nomodulenamed...

如何解決jieba分詞在景區評論分析中的問題?當我們在進行景區評論分析時,往往會使用jieba分詞工具來處理文�...

如何使用正則表達式匹配到第一個閉合標籤就停止?在處理HTML或其他標記語言時,常常需要使用正則表達式來�...

攻克Investing.com的反爬蟲策略許多人嘗試爬取Investing.com(https://cn.investing.com/news/latest-news)的新聞數據時,常常�...


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

WebStorm Mac版
好用的JavaScript開發工具

禪工作室 13.0.1
強大的PHP整合開發環境

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中