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:
- an abstract property
foo_propthat will be defined in the subclasses- the only way I could find to declare this was to create an abstract "property method"
- an abstract class method
get_somethingthat will be implemented in the subclasses - a concrete method
getthat 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
MyBaseClassset 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
-
similarly to what Engineero said, I also found a similar example to this scenario here:pymotw.com/2/abc/#concrete-methods-in-abcsGuy Avraham– Guy Avraham2019年08月22日 06:32:26 +00:00Commented Aug 22, 2019 at 6:32
1 Answer 1
According to the docs (text in brackets and code formatting mine):
[
@abstractpropertyis] 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
@abstractmethodand 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
abcinstead of manually setting the metaclass. I think this construction is preferred.
Comments
Explore related questions
See similar questions with these tags.