With multi-inheritance and super, raising NotImplementedError
is an anti-pattern.
Breaking the DRY principle
When __init__
raise a exception all subclass must repeat the initialization instead of using the default.
class BadBaseMatrix():
"""Init raise NotImplementedError"""
def __init__(self, text_version_of_matrix):
"""text_version_of_matrix represent some argument to initialize all matrix"""
# ...
raise NotImplementedError
class ComplexMatrix(BadBaseMatrix):
def __init__(self, text_version_of_matrix):
self.text_version_of_matrix = text_version_of_matrix
# ...
class OtherMatrix(BadBaseMatrix):
def __init__(self, text_version_of_matrix):
# Must redo the initialization here
self.text_version_of_matrix = text_version_of_matrix
# ...
instead of something like this
class BetterBaseMatrix():
def __init__(self, text_version_of_matrix):
"""text_version_of_matrix represent some argument to initialize all matrix"""
self.text_version_of_matrix = text_version_of_matrix
class ComplexMatrix(BetterBaseMatrix):
# ...
class PrintMatrix(BetterBaseMatrix):
def __init__(self, text_version_of_matrix):
super().__init__(text_version_of_matrix)
# in python 2, this would be super(MyMatrix, self)
print("PrintMatrix initialized")
Breaking inheritance
class MyMatrix(BadBaseMatrix):
def__init__(self, text_version_of_matrix):
# I will use his implementation because it must do some important initialization there.
super().__init__(text_version_of_matrix)
>>> matrix = MyMatrix("")
# NotImplementedError
Do you really need a abstract base class
I feel that in Python, you do not need to prevent consumers of using your class a certain way. Maybe the base class could be used as a valid container. If so, returning a correct default (possibly None
) would be enough for methods.
Here a similar version as your original of a plain matrix usable as a base class. But you should define each method to be able to add it's docstring.
class PlainMatrix():
def _do_nothing(*args, **kwargs):
"""This docstring is used for all methods ..."""
pass #
rotate = flip = _do_nothing
You really need a a abstract class
Use abc.ABCMeta.
import abc
class BaseMatrix(metaclass=abc.ABCMeta):
# In python 2,
# __metaclass__ = abc.ABCMeta
def __init__(self, text_version_of_matrix):
"""text_version_of_matrix represent some argument to initialize all matrix"""
self.text_version_of_matrix = text_version_of_matrix
@abc.abstractmethod
def rotate(self, degree):
""" Abstract rotate that must be implemented in subclass"""
pass
class SubMatrix(BaseMatrix):
def rotate(self, degree):
""" True implementation of rotate"""
# ...
class StillAbstractMatrix(BaseMatrix):
""" StillAbstractMatrix has not implemented rotate """
pass
>>> sub_matrix = SubMatrix("1 2 3")
>>> bad = StillAbstractMatrix("1 2 3")
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: Can't instantiate abstract class StillAbstractMatrix with abstract methods rotate