解决ABC内部的继承矛盾.序,阿克.可散列并在 Python 中列出



我正在使用3.6.3版

我正在研究 Pythoncollections.abc类之间的继承关系。我发现listSequenceHashable之间有一些矛盾的遗产

如您所知,
1.Sequence继承Hashable
2。list继承Sequence

from collections import Sequence, Hashable

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

由此,您可能认为list在概念上也继承了Hashable

但是list是可变的,它不会继承Hashable(意思是"你不能'哈希(some_list)')

issubclass(list, Hashable)

False

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

我等着你的到来。谢谢。

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

"如果一个性状适用于序列的连续成员之间,那么它也必须适用于按顺序排列的任何两个成员之间。例如,如果 A 大于 B,B 大于 C,则 A 大于 C。

对于继承是可传递的语言,例如Java,如果B继承A并且C继承B,则C必须继承AC的传递超类的集合是ABObject,直接超类是B

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

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

在 Python 中,您可以使用元类实用程序中的__subclasscheck____subclasshook__来使内置方法issubclass做有趣的事情。元类是一种高级语言功能,用于修改有关类如何操作的基本规则(修改issubclass的工作方式就是一个很好的例子)。在抽象基类元类ABCMeta中,__subclasscheck__方法将在类上调用__subclasshook__方法(如果它被定义)。您可以在此处阅读有关用途的精彩答案。

某些ABCMeta类(如Hashable实现__subclasshook__,不检查继承树,而是检查方法是否存在。这很有帮助,这样就不必将通用协定包含在您创建的每个类定义中。

对于这种情况,为了Hashable您需要定义__hash__。但是,Python 声明不在 List 上进行哈希处理,因为它是可变的,因此在此类中特别省略了它。

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

最新更新