I am currently writing an application that should be esily extensible, hence should be modular.
For that I write most of the modules using abstract classes / mixins, alongside with abstract methods.
Multiple times already I was facing the following question: I want to declare abstract methods for the purpose of uniform interfaces (ABC as meta base). Still I want to add some functionality to it so the implementation may call super() to reduce boilerplate code. Mostly this is for precondition checks.
Concretely I have following small example:
class ProbabilisticBehaviour(AbstractBaseModel):
"""
Model supports probabilistic outputs
"""
def supports_probability_scores(self) -> True:
return True
@abstractmethod
def predict_probabilities(self, pool: AbstractPool) -> typing.List[typing.Tuple[ProbabilityNumber, ...]]:
"""
Will predict probabilities for each element
that is: This function is expected to deliver an list of tuples of length |unique_labels| where
sum(tuple) == 1 for each element in list (exclusive multiclass output)
:param pool:
:return:
"""
if not self.is_fitted() or not self.accepts_pool_for_prediction(pool) or not self.supports_probability_scores():
raise ModelPredictException("This model does not support prediction of "
"probabilities or preconditions"
"are not met (Not fitted? Data format does not match?) (Code: 28347234)")
# override
Mixing this into a class works fine. Calling super().predict_probabilities
also works with no problems. Still, it leaves me with the feeling that this is not meant to be like that. My IDE (PyCharm) will complain for missing return statement in the function body. Still, I want to declare the return types there for documentation purposes. In addition, most implementations of abstracts I have seen are empty (pass
) or only raise NotImplementedError()
.
I also don't want to clutter the implementation with some abstract function like really_predict_probabilities
which is called by the then-non-abstract predict_probabilities
.
Is there a "Pythonic" way to do such things or do I just have to life with that?