Abstract base classes

The core of the abstract base class (ABC) definition is defined in a module named abc. This contains the required decorators and metaclasses to create abstractions. Other classes rely on these definitions. The collections.abc module uses the abc module to create abstractions focused on collections. We'll also look at the numbers module, because it contains ABCs for numeric types. There are ABCs for I/O in the io module, too.

An abstract base class has the following features:

  • Abstract means that these classes don't contain all the method definitions required to work completely. For it to be a useful subclass, we will need to provide some method definitions.
  • Base means that other classes will use it as a superclass.
  • An abstract class provides some definitions for methods. Most importantly, the abstract base classes often provide the signatures for the missing methods. A subclass must provide the right methods to create a concrete class that fits the interface defined by the abstract class.

Bear in mind the following when using abstract base classes:

  • When we use them to define our classes, they will be consistent with Python's internal classes.
  • We can use them to create some common, reusable abstractions that our application extends.
  • We can use them to support the proper inspection of a class to determine what it does. This allows better collaboration among library classes and new classes in our applications. It helps to start from the formal definitions of classes that will have similar behavior to other containers or numbers.

If we don't use abstract base classes, we can easily create a class that fails to provide all the features of the abstract base Sequence class. This will lead to a class being almost a sequence—we sometimes call it sequence-like. This can lead to odd inconsistencies and kludgy workarounds for a class that doesn't quite provide all the features of a Sequence class.

With an abstract base class, an application's class is guaranteed to have the advertised features of the abstract base class. If it lacks a feature, the presence of an undefined abstract method will make the class unusable for building object instances.

We will use ABCs in several situations, as follows:

  • We will use ABCs as superclasses when defining our own classes.
  • We will use ABCs within a method to confirm that an operation is possible.
  • We will use ABCs within a diagnostic message or exception to indicate why an operation can't work.

For the first use case, we can write modules with code that looks like the following:

import collections.abc 
class SomeApplicationClass(collections.abc.Sequence): 
    pass 

Our SomeApplicationClass is defined as a Sequence class. It must then implement the specific methods required by Sequence, or we will not be able to create an instance.

For the second use case, we can write methods with code as follows:

def some_method(self, other: Iterator): 
    assert isinstance(other, collections.abc.Iterator) 

Our some_method() requires the other argument to be a subclass of Iterator. If the other argument can't pass this test, we get an exception.

Instead of the assert statement, a common alternative is an if statement that raises TypeError, which may be more meaningful than AssertError. We'll see this in the following section.

For the third use case, we might have something like the following:

try: 
    some_obj.some_method(another) 
except AttributeError: 
    warnings.warn(f"{another!r} not an Iterator, found {another.__class__.__bases__!r}") 
    raise 

In this case, we wrote a diagnostic warning that shows the base classes for a given object. This may help debug problems with application design.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset