问题
This list shows what methods you need to implement for your class to be "regarded" as Sequence: __getitem__
, __len__
, __contains__
, __iter__
, __reversed__
, index
, and count
. So why does this minimal implementation does not work, i.e. why 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 :-(
Is there an additional method I need to implement that I overlooked? Did I misunderstand abstract base classes? Subclassing Sequence
makes issubclass
return True
of course, but that kinda defeats the idea behind abc, doesn't it?
回答1:
Use the source, Luke!
Sequence
does not implement its own __subclasshook__
, and all the implementations of __subclasshook__
from the parents of Sequence
have checks like this:
class Iterable:
...
@classmethod
def __subclasshook__(cls, C):
if cls is Iterable: # <<<<
if _hasattr(C, "__iter__"):
return True
return NotImplemented
You can however explicitly register() your class as a Sequence
:
Sequence.register(S)
As for the reason why Sequence
does not implement __subclasshook__
, see issue 16728 (which title was initially "collections.abc.Sequence shoud provide __subclasshook__"). The issue can be summarized by saying that a sequence can be many things, depending on the needs of who uses it:
Many algorithms that require a sequence only need
__len__
and__getitem__
. [...]collections.abc.Sequence
is a much richer interface.
来源:https://stackoverflow.com/questions/34927949/issubclass-of-abstract-base-class-sequence