Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does @abstractmethod need to be used in a class whose metaclass is derived from ABCMeta?

PEP 3119 states that:

The @abstractmethod decorator should only be used inside a class body, and only for classes whose metaclass is (derived from) ABCMeta. Dynamically adding abstract methods to a class, or attempting to modify the abstraction status of a method or class once it is created, are not supported.

I cannot find, however, an explanation of why that is. Specifically, I do not notice a difference in behavior when using only @abstractmethod in a class that does not explicitly inherit from ABCMeta. In the following simple example, if I understand correctly, the proper way of doing things would be:

import six
from abc import ABCMeta
from abc import abstractmethod

class Base(six.with_metaclass(ABCMeta)):
    def __init__(self):
        print('Init abstract base')

    @abstractmethod
    def do_something(self):
        pass

class Subclass(Base):
    def __init__(self):
        super(Subclass, self).__init__()

    def do_something(self):
        print('Done.')

sub = Subclass()
sub.do_something()

However, if I let the Base class inherit simply from object, and only use the decorator when needed, I notice no change in behavior.

from abc import abstractmethod

class Base(object):
    def __init__(self):
        print('Init abstract base')

    @abstractmethod
    def do_something(self):
        pass

class Subclass(Base):
    def __init__(self):
        super(Subclass, self).__init__()

    def do_something(self):
        print('Done.')

sub = Subclass()
sub.do_something()

I have found this to be the case even on more complex architectures, so I wonder: when does the latter method fail?

like image 656
Pietro Marchesi Avatar asked Dec 15 '16 12:12

Pietro Marchesi


People also ask

What is metaclass ABCMeta in Python?

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.

What is @abstractmethod in Python?

An abstract class in Python is typically created to declare a set of methods that must be created in any child class built on top of this abstract class. Similarly, an abstract method is one that doesn't have any implementation.

What is the difference between ABC and ABCMeta?

ABCMeta . i.e abc. ABC implicitly defines the metaclass for us. The only difference is that in the former case you need a simple inheritance and in the latter you need to specify the metaclass.

What is the purpose of ABC Python?

The 'abc' module in the Python library provides the infrastructure for defining custom abstract base classes. Abstract class cannot be instantiated in python. An Abstract method can be call by its subclasses.


1 Answers

You don't see any difference because your first subclass does implement the do_something abstractmethod.

Comment out the definition of do_something in the subclasses in both versions and you'll find out that in the first case you get a TypeError when trying to instanciate the subclass - you'd also get one trying to instanciate the first version Base class itself FWIW. With the second version, you can instanciate both classes (which shouldn't be possible since they are abstract) and call the abstract do_something method - which kind of defeats one of main points of ABCs.

You'll also miss quite a few other interesting features of ABCs FWIW...

like image 129
bruno desthuilliers Avatar answered Nov 15 '22 23:11

bruno desthuilliers