I'm wondering if in python (3) an abstract class can have concrete methods.
Although this seems to work I'm not sure this is the proper way to do this in python:
from abc import ABCMeta, abstractclassmethod, abstractmethod
class MyBaseClass:
__metaclass__ = ABCMeta
@property
@abstractmethod
def foo_prop(self):
"""Define me"""
pass
@abstractclassmethod
def get_something(cls, param1, param2, param3):
"""This is a class method, override it with @classmethod """
pass
@classmethod
def get(cls, param1, param2):
"""Concrete method calling an abstract class method and an abstract property"""
if param1 < cls.foo_prop:
raise Exception()
param3 = param1 + 42
item = cls.get_something(param1, param2, param3)
return item
class MyConcreteClassA(MyBaseClass):
"""Implementation """
foo_prop = 99
@classmethod
def get_something(cls, param1, param2, param3):
return cls.foo_prop + param1 + param2 + param3
class MyConcreteClassB(MyBaseClass):
"""Implementation """
foo_prop = 255
@classmethod
def get_something(cls, param1, param2, param3):
return cls.foo_prop - param1 - param2 - param3
In the example the abstract class MyBaseClass
has:
foo_prop
that will be defined in the subclasses
get_something
that will be implemented in the subclasses get
that in turns uses the (not yet defined) abstract method and property mentioned above.Questions:
Is there a better way to define an abstract property? Would it make more sense to define a concrete property in MyBaseClass
set to None and just redefine it in the subclasses?
Can I mix abstract and concrete methods in an abstract class as shown in the example?
If yes, does it always makes sense to declare the class abstract or can a concrete class have abstract methods (in this case it should never be instantiated directly anyway).
Thanks
According to the docs (text in brackets and code formatting mine):
[
@abstractproperty
is] Deprecated since version 3.3: It is now possible to useproperty
,property.getter()
,property.setter()
andproperty.deleter()
withabstractmethod()
, making this decorator redundant.
so I think you're doing it right.
You can do this, or at least in my experience it has not been an issue. Maybe somebody else can offer other advice, but that advice will probably take the form of "inheritance is bad". Although I don't see anything explicitly about it in the docs, this section shows an example wherein an abstract method, concrete method, and class method are all defined within an ABC.
I believe you still have to declare the class abstract in order to use @abstractmethod
and similar decorators. By setting the metaclass as ABC, the class cannot be instantiated until all abstract methods are defined, which sounds like the behavior that you want, so I think you need to declare it abstract unless you just want to rely on documentation to enforce the "you shall not instantiate" rule on this class. As an aside, you can declare your abstract class with:
from abc import ABC
class MyBaseClass(ABC):
# ...
inheriting from abc
instead of manually setting the metaclass. I think this construction is preferred.
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