解决abc.Sequence、abc.Hashable和Python中列表的继承矛盾
Solving inheritance contradictions among abc.Sequence, abc.Hashable and list in Python
我使用的是 3.6.3 版本
我正在研究 Python collections.abc
在 class 之间的继承关系。我发现 list
、Sequence
和 Hashable
之间存在一些矛盾的继承
如您所知,
1、Sequence
继承Hashable
class和
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
必须继承 A
。 C
的传递超 classes 的集合是 A
、B
和 Object
,直接超 class 是 B
.
在Python中我们背离了这个概念。正如您所指出的,Sequence
是 Hashable
,list
是 Sequence
,但 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
我使用的是 3.6.3 版本
我正在研究 Python collections.abc
在 class 之间的继承关系。我发现 list
、Sequence
和 Hashable
如您所知,
1、Sequence
继承Hashable
class和
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
必须继承 A
。 C
的传递超 classes 的集合是 A
、B
和 Object
,直接超 class 是 B
.
在Python中我们背离了这个概念。正如您所指出的,Sequence
是 Hashable
,list
是 Sequence
,但 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