Use of ABCMeta.register

Viewed 245

What is the use of ABCMeta's register method?

https://docs.python.org/3/library/abc.html

It seems that if I have an abstract base class ABC, say, Animal, I can register a subclass of it using register:

from abc import ABC

class Animal(ABC):
    pass

@Animal.register
class Dog:
    pass

But isn't this the very same as just defining the subclass as inheriting from the base class?

class Dog(Animal): # same as wrapping with Animal.register decorator?
    pass

In other words, is it just a way to kind of dynamically define inheritance? Or am I missing some things that this method does?

2 Answers

The concept of virtual base classes may seem funny if you come from a language with a different flavor of OOP.

There is a small example in the documentation of register that IMHO explains the concept of vitual base class

from abc import ABC

class MyABC(ABC):
    pass

MyABC.register(tuple)

assert issubclass(tuple, MyABC)
assert isinstance((), MyABC)

The assertions at the end of the code snippet are asking the following questions:

  1. Is the type tuple a subtype of MyABC.
  2. Is the literal () an instance of MyABC.

Since tuple is a builtin class and you can't redefine it, those assertions should fail, they don't because ABCMeta.register "makes" issubclass and isinstance believe that you modified the tuple type to inherit from MyABC when no actual inheritance is happening.

There are various use cases for this, you should take a look at the collections.abc module.

I believe the main use case for register is when you don't have control over the target class, Dog in your example.

Let's assume Dog is provided by a third-party library and you want to use it as one possible implementation (alongside others) of your ABC Animal. Then you could simply do:

Animal.register(Dog)

(Which, as opposed to using the decorator as in your example, does not require access to the implementation of Dog.)

Related