日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

詳解Python是如何實(shí)現(xiàn)issubclass的

系統(tǒng) 2505 0

使用Python內(nèi)置的issubclass方法很方便的檢測(cè)一個(gè)類是否是另一個(gè)類的子類。

這個(gè)是issubclass的文檔:

issubclass(class, classinfo)

Return true if class is a subclass (direct, indirect or virtual) of classinfo. A class is considered a subclass of itself. classinfo may be a tuple of class objects, in which case every entry in classinfo will be checked. In any other case, a TypeError exception is raised.

一個(gè)類的子類可以是直接的、間接的、或者是虛擬的。

issubclass的第二個(gè)參數(shù)classinfo可以是一個(gè)類對(duì)象或者包含類對(duì)象的tuple(只要其中一個(gè)檢測(cè)成功即返回True)。

一些使用示例:

            
>>> class A(object):
...   pass
...
>>> class B(A):
...   pass
...
>>> class C(B, A):
...   pass
...
>>> class D(C):
...   pass
...
>>> issubclass(D, D), issubclass(D, C), issubclass(D, B), issubclass(D, A), issubclass(D, object)
(True, True, True, True, True)
>>> D.__bases__
(
            
              ,)
>>> D.__mro__
(
              
                , 
                
                  , 
                  
                    , 
                    
                      , 
                      
                        )

                      
                    
                  
                
              
            
          

D是D的子類,D定義時(shí)的基類是C,所以D是C的子類,而且D是B,A,object的間接子類。

__mro__是類屬性, 在類定義完畢Python解析器便通過(guò)一種C3算法將所有的父類以method resolution order的順序保存到一個(gè)元組里, 成為類的屬性。

所以issubclass可以這樣簡(jiǎn)單的實(shí)現(xiàn):

            
def issubclass(cls, classinfo):
  if classinfo in cls.__mro__:
    return True
  return False

          

Python的issubclass是內(nèi)置函數(shù)(一般是C實(shí)現(xiàn)),實(shí)際上要復(fù)雜很多,要檢測(cè)參數(shù)類型,如第一個(gè)參數(shù)必須是type類型,第二個(gè)參數(shù)是type類型或者tuple類型。還要考慮該類是否是虛擬的子類,以及子類的子類。

例如:

            
>>> from collections import abc
>>> class E:
...   def __len__(self):
...     return 1
...
>>> issubclass(E, abc.Sized)
True
>>> E.__mro__
(
            
              , 
              
                )
>>> class F:
...   pass
...
>>> issubclass(F, abc.Sized)
False
>>> abc.Sized.register(F)

                
                  
>>> issubclass(F, abc.Sized)
True

                
              
            
          

Python是動(dòng)態(tài)類型語(yǔ)言,長(zhǎng)久以來(lái)使用Duck type(鴨子類型)形式編程,不管對(duì)象是什么類型,只要實(shí)現(xiàn)了所需要的方法。

現(xiàn)在有了ABCs, 可以用于判斷某個(gè)類或者某個(gè)對(duì)象是不是ABCs的子類或者實(shí)例,但這個(gè)類并不需要顯示的繼承于ABCs, 因?yàn)閜ython內(nèi)置的ABCs有一種注冊(cè)機(jī)制可將一個(gè)類注冊(cè)為它的子類。如上例子的register方法。

還有一種機(jī)制是可以定制一個(gè)__subclasshook__方法,將某種類型的類認(rèn)定為子類。

如abc.Sized的__subclasshook__是這樣子的:

            
@classmethod
def __subclasshook__(cls, C):
  if cls is Sized:
    if any("__len__" in B.__dict__ for B in C.__mro__):
      return True
  return NotImplemented

          

所以有__len__方法的E類是abc.Sized的子類, 這個(gè)__subclasshook__方法是通過(guò)__subclasscheck__方法調(diào)用的,這個(gè)__subclasscheck__是每一個(gè)ABC類都有的方法,在ABCMeta類(其他ABC類都繼承于它)實(shí)現(xiàn)。

現(xiàn)在的issubclass函數(shù)的實(shí)現(xiàn),會(huì)先判斷classinfo是否有__subclasscheck__方法,如果有此方法,則判斷子類的邏輯由該方法返回,即覆蓋issubclass的實(shí)現(xiàn)(CPython)。

__subclasscheck__會(huì)分幾個(gè)步驟進(jìn)行判斷:

  1. 調(diào)用__subclasshook__方法,如果有方法定義
  2. 檢查自己是否在待檢測(cè)類的__mro__列表里
  3. 遞歸檢查待檢測(cè)類是否是在注冊(cè)子類(內(nèi)置_abc_registry列表屬性)
  4. 遞歸檢查待檢測(cè)類是否是自己子類的子類

具體源碼在: https://github.com/python/cpython/blob/3.6/Lib/abc.py#L194-L231

相關(guān)的CPython實(shí)現(xiàn)在: https://github.com/python/cpython/blob/0ccc0f6c7495be9043300e22d8f38e6d65e8884f/Objects/abstract.c#L2223

而基本上isinstance(object, classinfo)方法的實(shí)現(xiàn)只需要調(diào)用issubclass(type(object), classinfo)

參考:

29.7. abc ― Abstract Base Classes : https://docs.python.org/3/library/abc.html
PEP 3119 ?C Introducing Abstract Base Classes: https://www.python.org/dev/peps/pep-3119/

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 浪卡子县| 商河县| 望江县| 蓝田县| 陆良县| 盐亭县| 达日县| 墨玉县| 浦北县| 广元市| 慈溪市| 静乐县| 石河子市| 彭山县| 阿瓦提县| 伊春市| 象州县| 景泰县| 郸城县| 多伦县| 湖南省| 鲁山县| 开平市| 东乡族自治县| 白银市| 临夏市| 延长县| 平凉市| 平武县| 常德市| 颍上县| 土默特左旗| 新化县| 涡阳县| 锦州市| 芒康县| 罗山县| 阜新| 绵竹市| 怀宁县| 贡嘎县|