解决abc.Sequence、abc.Hashable和Python中列表的继承矛盾

Solving inheritance contradictions among abc.Sequence, abc.Hashable and list in Python

我使用的是 3.6.3 版本

我正在研究 Python collections.abc 在 class 之间的继承关系。我发现 listSequenceHashable

之间存在一些矛盾的继承

如您所知,
1、Sequence继承Hashableclass
2.list继承Sequence

from collections import Sequence, Hashable


issubclass(Sequence, Hashable)  # 1.
issubclass(list, Sequence)      # 2.

True
True

据此,你可能会认为 list 在概念上也继承了 Hashable

但是 list 是可变的,它不会继承 Hashable(意味着 'you cannot 'hash(some_list)')

issubclass(list, Hashable)


False

我觉得这个继承是矛盾的。我完全理解 list 是可变的,因为我已经使用了 list 数百次,但是继承关系图不支持这个概念。我错了什么或遗漏了什么?

我等你的建议。谢谢。

所以它实际上是一个有趣的设计特性,但是 Python subclasses 实际上不需要传递。传递定义为 Google:

"if a trait is applicable between successive members of a sequence, it must also apply between any two members taken in order. For instance, if A is larger than B, and B is larger than C, then A is larger than C."

对于继承是传递的语言,例如Java,如果B继承A并且C继承B,那么C 必须继承 AC 的传递超 classes 的集合是 ABObject,直接超 class 是 B.

在Python中我们背离了这个概念。正如您所指出的,SequenceHashablelistSequence,但 list 不是 Hashable。事实上,list 不直接继承任何东西 (除了每个 python class 继承的 object.

# from the PyCharm generated stubs
class list(object):
    ...

在 Python 中,您可以使用 metaclass 实用程序中的 __subclasscheck____subclasshook__ 来使内置方法 issubclass 执行有趣的操作。元 class 是一种高级语言功能,用于修改有关 class 如何运行的基本规则 (修改 issubclass 的工作方式就是一个很好的例子) .在抽象基础 class metaclass ABCMeta 中,__subclasscheck__ 方法将调用 class 上的 __subclasshook__ 方法(如果已定义)。你可以读一个.

某些 ABCMeta class 像 Hashable 实现 __subclasshook__ 不检查继承树,而是检查方法的存在。这很有用,这样普通合同就不必包含在您所做的每个 class 定义中。

对于这种情况,要成为 Hashable,您需要定义 __hash__。但是,Python 声明不要在 List 上散列,因为它是可变的,因此在 class.

中特别省略了它
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