I have one base class with abstractmethod and subclass which implements this method. How to determine in runtime if in object (without checking type of object or calling method) that method is abstract or not?
class Base:
@abc.abstractmethod
def someAbstractMethod(self):
raise NotImplementedError("Not implemented yet.")
class Subclass(Base):
def someAbstractMethod(self):
some_operations
objects = [Base(),Subclass(),Base(),Subclass(),Subclass(),...]
for object in objects:
#here I want check if method is still abstract or not
Python prevents the creation of instances for classes with abstract methods. So just the fact that you have an instance means you have no abstract methods.
You do, however, have to use the ABCMeta
metaclass to properly trigger this behaviour:
class Base(metaclass=abc.ABCMeta):
@abc.abstractmethod
def someAbstractMethod(self):
raise NotImplementedError("Not implemented yet.")
You can also inherit from abc.ABC
to get the same metaclass via a base class.
If you wanted to see what abstract methods a class might have listed, use the __abstractmethods__
attribute; it is a set of all names that are still abstract:
>>> import abc
>>> class Base(metaclass=abc.ABCMeta):
... @abc.abstractmethod
... def someAbstractMethod(self):
... raise NotImplementedError("Not implemented yet.")
...
>>> class Subclass(Base):
... def someAbstractMethod(self):
... some_operations
...
>>> Base.__abstractmethods__
frozenset({'someAbstractMethod'})
>>> Subclass.__abstractmethods__
frozenset()
All that the @abc.abstractmethod
decorator does is set a __isabstractmethod__
attribute on the function object; it is the metaclass that then uses those attributes.
So if you are dig in too deep or are using a third-party library that has forgotten to use the ABCMeta
metaclass, you can test for those attributes:
>>> class Base: # note, no metaclass!
... @abc.abstractmethod
... def someAbstractMethod(self):
... raise NotImplementedError("Not implemented yet.")
...
>>> getattr(Base().someAbstractMethod, '__isabstractmethod__', False)
True
If you need to 'repair' such broken abstract base classes, you'd need subclass and mix in ABCMeta
, and add a __abstractmethods__
frozenset to the class you are inheriting from:
BaseClass.__abstractmethods__ = frozenset(
name for name, attr in vars(BaseClass).items()
if getattr(attr, '__isabstractmethod__', False))
class DerivedClass(BaseClass, metaclass=abc.ABCMeta):
# ...
Now DerivedClass
is a proper ABC-derived class where any abstract methods are properly tracked and acted on.
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