为什么CPubthon中的issubclass(dict,collections.Mapping)是真的?

在C
Python中如下

import collections
issubclass(dict, collections.Mapping)

返回True.这让我感到困惑,因为dict是CTypes中定义的内置类,而collections模块显式依赖于dict的存在来完成它的一些功能.除了直接的继承检查之外的东西必须继续进行,我无法弄清楚为什么这样做.下面我提供一些导致我困惑的推理.

如果我们看一下collections.Mapping的继承结构,我们会看到它继承自Collection. Collection‘s signature显示它继承自Sized,Iterable,Container,所有这些只从元类ABCmeta继承.

但是dict是一个内置的,我认为这意味着它被直接定义为一个CType,我认为这意味着它不会继承任何东西.

那么,为什么是issubclass(dict,collections.Mapping)→True?

有关为什么出现这种情况的更多背景请参见this nbformat issue,其中尝试重新创建签名& dict更新的功能我们需要知道issubclass(foo,Mapping)的行为方式.

最佳答案 这是因为元类可以自定义
issubclass
isinstance返回的内容.在MutableMapping的情况下,这是通过
abc.ABCMeta完成的,这允许
register“虚拟子类”.

例如:

from collections import MutableMapping

class A(object): pass
MutableMapping.register(A)
issubclass(A, MutableMapping)  # True

它甚至适用于已注册子类的子类:

class B(object): pass
class C(B): pass
MutableMapping.register(B)
issubclass(C, MutableMapping)  # True

dict也是如此.因此即使它不是MutableMapping的真正子类,它仍然是一个虚拟子类.就像第二个例子所示,这意味着dict的所有“真正”子类也将是MutableMapping的“虚拟”子类.

请注意,即使是更简单的ABC也会根据方法的存在来实现子类检查.例如collections.Sized checks if the class has a __len__

from collections import Sized

class D(object):
    def __len__(self):
        return 1

issubclass(D, Sized)   # True

因此,即使没有显式寄存器,这个D也将被识别为Sized的有效子类.

点赞