If I create an abstract class in python using abc
with an abstractmethod as follows and create a concrete class which doesn’t use def
to override the abstractmethod but instead attempt to set the attribute in the init function, it continues to throw the error that we can’t instantiate an abstract class. I found out that I can get around this problem by creating a dummy of the abstractmethod. Is this the recommended way?
from abc import ABC, abstractmethod
class MyAbstract(ABC):
def __init__(self):
pass
@abstractmethod
def hi(self):
pass
class Concrete(MyAbstract):
def __init__(self, selector):
if selector:
self.hi = self.hi_a
else:
self.hi = self.hi_b
def hi(self):
'''
Is it possible to not have to create this function?
'''
pass
def hi_a(self):
print('a')
def hi_b(self):
print('b')
1
class Concrete(MyAbstract):
hi = None
...
This suffices to allow instantiation. The class simply mustn’t have any attribute decorated with @abstractXXX
at time of instantiation. Replacing the inherited hi
with any other hi
is enough to achieve that.
From documentation:
A class that has a metaclass derived from ABCMeta cannot be
instantiated unless all of its abstract methods and properties are
overridden.
and
Dynamically adding abstract methods to a class, or attempting to
modify the abstraction status of a method or class once it is created,
are only supported using the update_abstractmethods() function.
found out that I can get around this problem by creating a dummy of
the abstractmethod. Is this the recommended way?
Yes, a dummy method or attribute is necessary to tell ABC that the abstract method has been supplied.
Normally, if a method is dynamically added to a class, you can trigger an update to __abstractmethods__
by calling update_abstractmethods(cls)
. However, your code adds a bound method to the instance. This won’t be detected by the ABC logic. So, nothing short of putting a dummy in the class will suffice since the dynamic update is only done to the instance.