Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why we declare metaclass=abc.ABCMeta when use abstract class in python?

When I was reading the code online, I have encountered the following cases of using abstract classes:

from abc import abstractmethod,ABCMeta
class Generator(object,metaclass=ABCMeta):
    @abstractmethod
    def generate(self):
        raise NotImplementedError("method not implemented")
generator=Generator()
generator.generate()

The following error is returned, as expected:

TypeError: Can't instantiate abstract class Generator with abstract methods generate

But if I write it like this (the only difference is in the second line)

from abc import abstractmethod,ABCMeta
class Generator(object):
    @abstractmethod
    def generate(self):
        raise NotImplementedError("method not implemented")
generator=Generator()
generator.generate()

Although there are changes in the error message,

NotImplementedError: method not implemented

When I implemented the generate method, both of the above ways of Generator were executed correctly,

class GeneticAlgorithm(Generator):
    def generate(self):
        print("ABC")
ga=GeneticAlgorithm()
ga.generate()
>>> ABC

So why do we need the statement metaclass=ABCMeta?

I know something from GeeksforGeeks that

ABCMeta metaclass provides a method called register method that can be invoked by its instance. By using this register method, any abstract base class can become an ancestor of any arbitrary concrete class.

But this still doesn't make me understand the necessity of declaring metaclass=ABCMeta, it feels like @abstractmethod modifying the method is enough.

like image 374
XiaoBanni Avatar asked Sep 15 '25 22:09

XiaoBanni


1 Answers

You "need" the metaclass=ABCMeta to enforce the rules at instantiation time.

generator=Generator()  # Errors immediately when using ABCMeta
generator.generate()   # Only errors if and when you call generate otherwise

Imagine if the class had several abstract methods, only some of which were implemented in a child. It might work for quite a while, and only error when you got around to calling an unimplemented method. Failing eagerly before you rely on the ABC is generally a good thing, in the same way it's usually better for a function to raise an exception rather than just returning None to indicate failure; you want to know as soon as things are wrong, not get a weird error later without knowing the ultimate cause of the error.

Side-note: There's a much more succinct way to be an ABC than explicitly using the metaclass=ABCMeta syntax:

from abc import abstractmethod, ABC

class Generator(ABC):

Python almost always makes empty base classes that use the metaclass to simplify use (especially during the 2 to 3 transition period, where there was no compatible metaclass syntax that worked in both, and direct inheritance was the only thing that worked).

like image 124
ShadowRanger Avatar answered Sep 19 '25 08:09

ShadowRanger