python基本数据结构dict继承自object,但为什么又是MutableMapping的子类

dict是抽象类MutableMapping的一个子类

>>> from collections.abc import MutableMapping
>>> isinstance(dict(),MutableMapping)
True

但是在builtin.py中可以看到dict是继承自object对象。

所以我就产生了疑问,dict到底是如何实现继承MutableMapping的呢,是直接继承还是有一些中间环节。
MutableMapping是继承object的吗,这三者之间的关系到底是怎样的。

我了解到dict的实现应当是由解释器内部实现的。
我知道这大概涉及到python解释器的内部原理了,我对此很感兴趣。

MutableMapping也是由解释器内部实现的吗?
然后dict和MutableMapping在解释器内部实现了继承关系

阅读 6.7k
3 个回答

isinstance 除了会依据类的 mro 来判断,也会基于 鸭子协议 来判断对象是否满足某个类型的行为。比如 list 对象是直接继承自 object 。但它本身也能够跌倒,它属于可迭代对象。通过 isinstance([], typing.Iterable) 返回的是真。这部分和 __instancecheck__ 魔术方法有关,根据 PEP 3119 的描述中得知实例的检查是允许重载的。

The primary mechanism proposed here is to allow overloading the built-in functions isinstance() and issubclass(). The overloading works as follows: The call isinstance(x, C) first checks whether C.__instancecheck__ exists, and if so, calls C.__instancecheck__(x) instead of its normal implementation. Similarly, the call issubclass(D, C) first checks whether C.__subclasscheck__ exists, and if so, calls C.__subclasscheck__(D) instead of its normal implementation.

大致意思是调用 isinstance(x,C) 时先检查 C.__ instancecheck__ 是否存在,如果存在,则调用 C.__ instancecheck __(x)而不是其正常实现(从类的 mro 来判断)。

MutableMapping 应该也是通过重载的方式实现了对"子类"的判断。

相关文章:深度剖析isinstance的检查机制

因为python内置的dict类实际上没有继承MutableMapping类,C语言编写的内置类型怎么可能继承自python语言编写的抽象基类呢?检查下dict类的MRO方法解析列表,它的“真实”基类们就一清二楚了:

>>> dict.__mro__
(<class 'dict'>, <class 'object'>)

那么为何通过函数检查dict,python又会告诉你“dict是MutableMapping的子类”呢?

>>> import collections
>>> issubclass(dict, collections.abc.MutableMapping)
True

因为python的抽象基类能够【注册虚拟子类】:在你import collections包时,该包的代码就已经执行了MutableMapping.register()方法,将dict注册为了自己的虚拟子类,从而可以通过函数检查。

想从python代码的角度研究dict的行为及其继承关系?没问题,官方提供了python代码版本的dict类,即UserDict类,专供程序员继承/改造自定义的映射类型。

>>> from collections import UserDict
>>> UserDict.__mro__
(<class 'collections.UserDict'>, <class 'collections.abc.MutableMapping'>, <class 'collections.abc.Mapping'>, <class 'collections.abc.Collection'>, <class 'collections.abc.Sized'>, <class 'collections.abc.Iterable'>, <class 'collections.abc.Container'>, <class 'object'>)

python里的对象是“鸭子类型”,太过灵活,导致难以准确判断某个对象是不是某类的实例。
collections.abc是抽象基本类的意思,abc约束和定义了类的基本特征,就可以用isinstanceissubclass来判断实例和子类了。

abc

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏