24

I need something like an abstract protected method in Python (3.2):

class Abstract:
    def use_concrete_implementation(self):
        print(self._concrete_method())

    def _concrete_method(self):
        raise NotImplementedError()


class Concrete(Abstract):
    def _concrete_method(self):
        return 2 * 3

Is it actually useful to define an "abstract" method only to raise a NotImplementedError?

Is it good style to use an underscore for abstract methods, that would be protected in other languages?

Would an abstract base class (abc) improve anything?

3 Answers 3

46

In Python, you usually avoid having such abstract methods alltogether. You define an interface by the documentation, and simply assume the objects that are passed in fulfil that interface ("duck typing").

If you really want to define an abstract base class with abstract methods, this can be done using the abc module:

from abc import ABCMeta, abstractmethod

class Abstract(metaclass=ABCMeta):
    def use_concrete_implementation(self):
        print(self._concrete_method())

    @abstractmethod
    def _concrete_method(self):
        pass

class Concrete(Abstract):
    def _concrete_method(self):
        return 2 * 3

Again, that is not the usual Python way to do things. One of the main objectives of the abc module was to introduce a mechanism to overload isinstance(), but isinstance() checks are normally avoided in favour of duck typing. Use it if you need it, but not as a general pattern for defining interfaces.

Sign up to request clarification or add additional context in comments.

4 Comments

Great point about this not being a "pythonic problem" to begin with.
But why not "document" with the code itself and raise a NotImplementedError in the body of the "abstract" method?
@deamon: If you simply omit the method, you get an AttributeError. If you implement it raising NotImplementedError, you get the latter exception instead. If you feel that the different error message is worth the additional code, go for it :) I often consider the AttributeError to be clear enough, but there might be situations where you want things to be even more explicit.
class Abstract(metaclass=ABCMeta) works only in Python 3, right?
10

When in doubt, do as Guido does.

No underscore. Just define the "abstract method" as a one-liner which raises NotImplementedError:

class Abstract():
    def ConcreteMethod(self):
        raise NotImplementedError("error message")

6 Comments

... but Guido uses underscore for abstract "protected" methods ;-)
And why would you name an abstract method Conrete?
@Ethan Furman: Because the programmer is expected to implement the method of that name. The abstract class have to always name the abstract method using the to-be-used-later name.
@pepr: Oh, right -- can I claim being really tired when I asked that? Garden Fatigue, maybe? ;)
|
0

Basically, an empty method in the base class is not necessary here. Just do it like this:

class Abstract:
    def use_concrete_implementation(self):
        print(self._concrete_method())

class Concrete(Abstract):
    def _concrete_method(self):
        return 2 * 3

In fact, you usually don't even need the base class in Python. Since all calls are resolved dynamically, if the method is present, it will be invoked, if not, an AttributeError will be raised.

Attention: It is import to mention in the documentation that _concrete_method needs to be implemented in subclasses.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.