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?

Asked By: ostrokach

||

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
Answered By: Martijn Pieters

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

Quote:

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):

  1. 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.
  2. Just using pass is also quite common.
  3. 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.
Answered By: Neuron