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.
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).
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