collections.abc 的实施不一致

Inconsistent implementation of collections.abc

我正在尝试理解 collections.abc 源代码。

让我们来看看 Hashable class' __subclasshook__ 实现:

@classmethod
def __subclasshook__(cls, C):
    if cls is Hashable:
        for B in C.__mro__:
            if "__hash__" in B.__dict__:
                if B.__dict__["__hash__"]:
                    return True
                break
    return NotImplemented

这里我们首先检查是否存在属性 hash,然后检查它是否具有非假值。 Awaitable class.

中也有此逻辑

AsyncIterable class' __subclasshook__:

@classmethod
def __subclasshook__(cls, C):
    if cls is AsyncIterable:
        if any("__aiter__" in B.__dict__ for B in C.__mro__):
            return True
    return NotImplemented

这里我们只是检查是否有 __aiter___ 属性,这个逻辑在这个包中的任何其他 classes 中都存在。

这种逻辑差异有什么原因吗?

__hash__ protocol 通过设置 __hash__ = None.

明确允许将 class 标记为不可哈希

If a class [...] wishes to suppress hash support, it should include __hash__ = None in the class definition.

原因是 a == b 总是需要 hash(a) == hash(b)。否则,dictset 和类似的数据结构会中断。如果 child class 明确或以其他方式更改 __eq__,这可能不再适用。因此,__hash__ 可以标记为不适用。