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?
An abstract class is a class that is designed to be specifically used as a base class. An abstract class contains at least one pure virtual function. You declare a pure virtual function by using a pure specifier ( = 0 ) in the declaration of a virtual member function in the class declaration.
Abstract base classes separate the interface from the implementation. They make sure that derived classes implement methods and properties dictated in the abstract base class. Abstract base classes separate the interface from the implementation.
Abstract base classes provide a way to define interfaces when other techniques like hasattr() would be clumsy or subtly wrong (for example with magic methods). ABCs introduce virtual subclasses, which are classes that don't inherit from a class but are still recognized by isinstance() and issubclass() functions.
Abstract classes are classes that contain one or more abstract methods. An abstract method is a method that is declared, but contains no implementation. Abstract classes cannot be instantiated, and require subclasses to provide implementations for the abstract methods.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With