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

时间:2017-08-18 01:08:02

标签: python dictionary inheritance

在CPython中以下

import collections
issubclass(dict, collections.Mapping)

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

如果我们查看collections.Mapping的继承结构,我们会看到它继承自CollectionCollection's signature表明它继承自SizedIterableContainer,所有这些都只从元类ABCmeta继承。

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

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

有关其原因的更多背景请参阅this nbformat issue,其中尝试重新创建签名& dict update的功能我们需要了解issubclass(foo, Mapping)的行为方式。

2 个答案:

答案 0 :(得分:4)

Because this:

MutableMapping.register(dict)

明确register编辑MutableMappingabc.ABCMeta定义issubclass检查,以便将注册的类视为isinstance的子类}和issubclass使用__instancecheck____subclasscheck__挂钩进行检查。

答案 1 :(得分:3)

这是因为元类可以自定义issubclassisinstance返回的内容。如果是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的子类。

请注意,即使是更简单的ABCs也会根据方法的存在来实现子类检查。例如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

即使没有明确的register,这个D也会被视为Sized的有效子类。