我正在使用3.6.3版
我正在研究 Pythoncollections.abc
类之间的继承关系。我发现list
、Sequence
和Hashable
之间有一些矛盾的遗产
如您所知,
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
必须继承A
。C
的传递超类的集合是A
、B
和Object
,直接超类是B
。
在Python中,我们偏离了这个概念。正如您所指出的,Sequence
是Hashable
,list
是Sequence
,但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