abc module in Python

Posted by chunyang on October 16, 2019
TAGS: #python

Introduction

abc is short for Abstract Base Class. Usually we use it to create a base class and force the subclass to implement certain functions. In python, abc is similar to C++’s abstract class.

There are three ways we can create this kind of class.

from abc import ABC, ABCMeta
from abc import abstractmethod

class Base1(ABC):
    @abstractmethod
    def hi(self):
         raise NotImplementedError("HH")

class Base2(metaclass=ABCMeta):
    @abstractmethod
    def hi(self):
        raise NotImplementedError("HH")

class Base3(object):
    __metaclass__ = ABCMeta
    @abstractmethod
    def hi(self):
        raise NotImplementedError("HH")

abc Module

  • ABCMeta
    • This should be the meta class of any class that wants to be the abc.
  • ABC
    • Just a simple wrapper, its meta class = ABCMeta. Users can directly inherit from it.
  • ABCMeta.register
    • Dynamically register any class and issubclass, isinstance will return True after registration.
    • Will not affect the MRO mechanism
  • abstractmethod:
    • If working with other decorators, please make sure that this is the first one. For example working with property or classmethod

collections.abc Module

Reference

Class Inherits from Required methods Mixin methods
Sized   __len__  
Awaitable   __await__  
Coroutine Awaitable send;throw close
AsyncIterable   __aiter__  
AsyncIterator AsyncIterable __anext__ __aiter__
ASyncGenerator AsyncIterator asend, athrow aclose
Iterable   __iter__  
Callable   __call__  
Hashable   __hash__  
Reversable Iterable __reversed__  
Iterator Iterable __next__ __iter__
Generator Iterator send, throw close, __iter__, __next__
Container   __contains__  
MutableSequence      
Collection Container
Iterable
Sized
__contains__
__iter__
__len__
 
Sequence Reversable
Collection
__getitem__;__len__ __contains__;__iter__
__reversed__;index;count
MutableSequence Sequence __getitem__;__setitem__
__delitem__;__len__;insert
Inherited from Sequence,append
reverse,extend, pop, remove, __iadd__
ByteString Sequence __getitem__, __len__ Inherit from Sequence
Set Collection __contains__
__iter__,__len__
__le__, __lt__, __eq__, __ne__, __gt__, __ge__
__and__, __or__, __xor__, __sub__, isdisjoint
MutableSet Set __contains__
__iter__, __len__, add, discard
Inhert from Set, clear, pop
remove
__ior__, __iand__, __ixor__, __isub__
Mapping Collection __getitem__, __iter__, __len__ __contains__, keys, items, values
get, __eq__, __ne__
MutableMapping Mapping __getitem__, __setitem__
__delitem__
__iter__, __len__
pop, popitem
clear, update, setdefault

*View related base classes are ommited.

Animal example

from abc import ABC, abstractmethod

class Animal(ABC):

    @abstractmethod
    def talk(self):
        pass

class Dog(Animal):

    def talk(self):
        print("Wang!")

class Cat(Animal):

    def talk(self):
        print("Meow!")


class Snake(object):

    def x(self):
        print("x")

Animal.register(Snake)

class Bird(Animal):
    pass

Dog().talk()
Cat().talk()
print(issubclass(Snake, Animal)) # True
print(isinstance(Snake(), Animal)) # True
# TypeError: Can't instantiate abstract class Bird with abstract methods talk
bird = Bird()

AwesomeSequence

from collections.abc import Iterable

class AwesomeSequence(Iterable, Callable):

    def __init__(self):
        self._a = 1
        self._b = 0
        self._c = 2
        self._d = 4

    def __iter__(self):
        yield self._a
        yield self._b
        yield self._c
        yield self._d

    def __call__(self):
        return iter(self)

c = AwesomeSequence()
for v in iter(c):
    print(v)

for v in c():
    print(v)