issubclass of abstract base class 序列

issubclass of abstract base class Sequence

This list 显示您需要实施哪些方法才能使 class 成为 "regarded" 作为序列:__getitem____len____contains____iter____reversed__indexcount。那么为什么这个最小的实现不起作用,即为什么 issubclass(S, Sequence) is False?

from collections import *


class S(object):
    def __getitem__(self, item):
        raise IndexError

    def __len__(self):
        return 0

    def __contains__(self, item):
        return False

    def __iter__(self):
        return iter(())

    def __reversed__(self):
        return self

    def index(self, item):
        raise IndexError

    def count(self, item):
        return 0


issubclass(S, Iterable)   # True  :-)
issubclass(S, Sized)      # True  :-)
issubclass(S, Container)  # True  :-)
issubclass(S, Sequence)   # False :-(

是否有我需要实施的其他方法被我忽略了?我是不是误解了 abstract base classes? Subclassing Sequence 使 issubclass return True 当然,但这有点违背 abc 背后的想法,不是吗?

Use the source, Luke!

Sequence 没有实现它自己的 __subclasshook__,并且 Sequence 的 parents 中 __subclasshook__ 的所有实现都有这样的检查:

class Iterable:
    ...

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Iterable:  # <<<<
            if _hasattr(C, "__iter__"):
                return True
        return NotImplemented

然而,您可以明确地 register() 您的 class 作为 Sequence:

Sequence.register(S)

至于Sequence没有实现__subclasshook__的原因,见issue 16728(标题最初是"collections.abc.Sequence shoud provide __subclasshook__" ).这个问题可以概括为一个序列可以是很多东西,这取决于使用它的人的需要:

Many algorithms that require a sequence only need __len__ and __getitem__. [...] collections.abc.Sequence is a much richer interface.