解决Python中abc.Sequence、abc.Hashable和list之间的继承矛盾

解决Python中abc.Sequence、abc.Hashable和list之间的继承矛盾,python,abc,Python,Abc,我使用的是3.6.3版 我正在研究Pythoncollections.abc类之间的继承关系。我发现列表,序列和哈希表 如您所知, 1. 序列继承哈希类和 2. 列表继承序列 从集合导入序列,可散列 issubclass(序列,可散列)#1。 issubclass(列表、序列)#2。 真的 真的 从这一点上,您可能会认为列表在概念上也继承了哈希表 但是列表是可变的,它不会继承哈希表(意思是“你不能”哈希表(一些列表)” issubclass(列表,可哈希) 假的 我认为这种继承是矛盾的。我完

我使用的是3.6.3版

我正在研究Python
collections.abc
类之间的继承关系。我发现
列表
序列
哈希表

如您所知,
1.
序列
继承
哈希类

2.
列表
继承
序列

从集合导入序列,可散列
issubclass(序列,可散列)#1。
issubclass(列表、序列)#2。
真的
真的
从这一点上,您可能会认为
列表
在概念上也继承了
哈希表

但是
列表
是可变的,它不会继承
哈希表
(意思是“你不能”哈希表(一些列表)”

issubclass(列表,可哈希)
假的
我认为这种继承是矛盾的。我完全理解
list
是可变的,因为我已经使用
list
数百次了,但是继承关系图不支持这个概念。我错了或错过了什么


我在等你的告别。谢谢。

所以它实际上是一个有趣的设计特性,但是Python子类实际上不需要是可传递的。谷歌定义的可传递性:

如果一个特征适用于一个序列的连续成员,它必须也适用于按顺序选取的任何两个成员。例如,如果a大于B,B大于C,则a大于C

对于继承是可传递的语言,如Java,如果
B
继承
A
C
继承
B
,则
C
必须继承
A
C
的可传递超类集将是
A
B
对象
,直接超类是
B

在Python中,我们背离了这个概念。正如您所指出的,
序列
是可散列的,
列表
是可散列的,但
列表
不是可散列的。事实上,list并没有直接继承任何东西(除了每个python类继承的
object

在Python中,您可以使用元类实用程序中的
\uuuuuu subasscheck\uuuuu
\uuuuuuuu subasshook\uuuuuu
使内置方法
issubclass
执行有趣的操作。元类是一种高级语言功能,用于修改有关类如何操作的基本规则(修改
issubclass
的工作方式就是一个很好的例子)。在抽象基类元类
ABCMeta
中,
\uuuuuu subasscheck\uuuuu
方法将调用类上的
\uuuuuuu subasshook\uuuuu
方法(如果已定义)。你可以读一本书

某些
ABCMeta
类,如
Hashable
实现
\uuu子类hook\uuuu
以不检查继承树,而是检查方法的存在。这很有帮助,这样就不必在所做的每个类定义中都包含公共契约

在这种情况下,为了能够
散列
,您需要定义
\uuuuuu散列
。然而,Python声明不在列表上散列,因为它是可变的,因此在这个类中特别省略了它

class Hashable(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __hash__(self):
        return 0

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Hashable:
            return _check_methods(C, "__hash__")
        return NotImplemented

class list(object):
    ...
    __hash__ = None

你看过这个博客吗?这看起来很好,这里有一个引语,“…Iterable是Hashable的一个“子类”——说真的,因为Iterable有它从object继承的
\uuuuuhash\ucode>方法,
Sequence
有一个
\uhash\uuhash
方法,但是根据,
Sequence
没有从
Hashable
继承。(不是回答,只是观察。)@SuperShoot谢谢你的推荐。我非常喜欢这种方法:用Python获取所有类并测试所有三元组依赖性检查。我想我以后应该深入研究
元类
。)我也把它加入了我的阅读清单。感谢您在Python学习中的出色表现。
类列表(对象):
不会出现在
列表
类的实际定义中的任何地方<代码>类列表(对象)
出现在
帮助(列表)
输出中,它可能会出现在PyCharm伪源代码或类似的东西中,但是在C@user2357112中。谢谢,很好的一点,我会添加进去。但列表只继承对象仍然是事实;由于是python对象,谢谢你,我的朋友。非常有趣的是,Python类并不仅仅遵循概念继承树。但是你能告诉我传递的意思吗?我不会说英语,所以这让我有点困惑。@flakes谢谢,你编辑的答案更清楚。但这也给我带来了更多的问题。为什么您的代码实现了
子类钩子
,而不是
子类检查
,什么是
检查方法
?“我说得有道理,我很感激。”“请知道,我真的很感激你做出了一个没有错误、更清晰的回答。我的Python有所改进。非常感谢:)
class Hashable(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __hash__(self):
        return 0

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Hashable:
            return _check_methods(C, "__hash__")
        return NotImplemented

class list(object):
    ...
    __hash__ = None