5

このリストは、クラスが Sequence として「見なされる」ために実装する必要があるメソッドを示しています: __getitem____len____contains____iter____reversed__indexおよびcount. では、なぜこの最小限の実装が機能しないの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 :-(

私が見落としていた、実装する必要がある追加の方法はありますか? 抽象基底クラスを誤解していませんか? もちろん、サブクラス化Sequenceは元issubclassに戻りますTrueが、それは abc の背後にあるアイデアを打ち負かしますよね?

4

1 に答える 1

11

ソースを使え、ルーク!

Sequenceは独自の を実装しておらず、 の親からの の__subclasshook__すべての実装には次のようなチェックがあります。__subclasshook__Sequence

class Iterable:
    ...

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

register()ただし、クラスを次のように明示的に指定できますSequence

Sequence.register(S)

Sequenceが を実装しない理由については、問題 16728__subclasshook__を参照してください(最初のタイトルは"collections.abc.Sequence shoud provide __subclasshook__" でした)。この問題は、シーケンスを使用する人のニーズに応じて、多くのものになる可能性があるということで要約できます。

シーケンスを必要とする多くのアルゴリズムは、 と のみを必要__len__とし__getitem__ます。[...]collections.abc.Sequenceはよりリッチなインターフェースです。

于 2016-01-21T15:41:55.733 に答える