What should I put in the body of an abstract method?
Question:
Say I have the following abstract class Foo
:
import abc
class Foo(abc.ABC):
@abc.abstractmethod
def bar(self):
raise NotImplementedError
What should I put in the body of the bar
method?
I see a lot of code that has raise NotImplementedError
, as shown above. However, this seems redundant, since any subclass that does not implement bar
will raise the TypeError: Can't instantiate abstract class Foo with abstract methods bar
when it is instantiated.
Is it Pythonic to leave bar
empty, as follows:
import abc
class Foo(abc.ABC):
@abc.abstractmethod
def bar(self):
...
This is what is done in the Python docs for Abstract Base Classes, but I’m not sure if that’s just a placeholder or an actual example of how to write code.
If it’s ok to leave bar
with only three dots (...
), when should I use NotImplementedError
?
Answers:
The documentation does aim to give you an example. You don’t have to follow it.
You could provide a default; subclasses are still free to use super()
to call your implementation. This is what most of the collections.abc
classes do; see the source code.
Size
for example, returns 0
for __len__
:
class Sized(metaclass=ABCMeta):
# ...
@abstractmethod
def __len__(self):
return 0
As Martijn Pieters has said, provide a default in places where a default makes sense.
If you want to communicate to your user that they absolutely should override it, use raise NotImplementedError
like so:
class FooBar(abc.ABC):
@abstractmethod
def foo(bar):
"""This method foos some bars"""
raise NotImplementedError
exception NotImplementedError
This exception is derived from RuntimeError
. In user defined base classes, abstract methods should raise this exception when they require derived classes to override the method, or while the class is being developed to indicate that the real implementation still needs to be added.
For completeness sake, here are some other things I have seen out in the wild (contradicting the official recommendation about raise NotImplementedError
):
- Instead of raising, just use Ellipses (
...
). this has some official support, since it is how the official python documentation for Abstract Base Classes uses it.
- Just using
pass
is also quite common.
- Actually, just using a docstring is sufficient. Imho any method should have a docstring anyways, so this would be more elegant than either
...
or pass
.
Say I have the following abstract class Foo
:
import abc
class Foo(abc.ABC):
@abc.abstractmethod
def bar(self):
raise NotImplementedError
What should I put in the body of the bar
method?
I see a lot of code that has raise NotImplementedError
, as shown above. However, this seems redundant, since any subclass that does not implement bar
will raise the TypeError: Can't instantiate abstract class Foo with abstract methods bar
when it is instantiated.
Is it Pythonic to leave bar
empty, as follows:
import abc
class Foo(abc.ABC):
@abc.abstractmethod
def bar(self):
...
This is what is done in the Python docs for Abstract Base Classes, but I’m not sure if that’s just a placeholder or an actual example of how to write code.
If it’s ok to leave bar
with only three dots (...
), when should I use NotImplementedError
?
The documentation does aim to give you an example. You don’t have to follow it.
You could provide a default; subclasses are still free to use super()
to call your implementation. This is what most of the collections.abc
classes do; see the source code.
Size
for example, returns 0
for __len__
:
class Sized(metaclass=ABCMeta):
# ...
@abstractmethod
def __len__(self):
return 0
As Martijn Pieters has said, provide a default in places where a default makes sense.
If you want to communicate to your user that they absolutely should override it, use raise NotImplementedError
like so:
class FooBar(abc.ABC):
@abstractmethod
def foo(bar):
"""This method foos some bars"""
raise NotImplementedError
exception
NotImplementedError
This exception is derived from
RuntimeError
. In user defined base classes, abstract methods should raise this exception when they require derived classes to override the method, or while the class is being developed to indicate that the real implementation still needs to be added.
For completeness sake, here are some other things I have seen out in the wild (contradicting the official recommendation about raise NotImplementedError
):
- Instead of raising, just use Ellipses (
...
). this has some official support, since it is how the official python documentation for Abstract Base Classes uses it. - Just using
pass
is also quite common. - Actually, just using a docstring is sufficient. Imho any method should have a docstring anyways, so this would be more elegant than either
...
orpass
.