[Python-Dev] A proposal: built in support for abstract methods

Noam Raphael noamraph at gmail.com
Wed Feb 2 23:55:31 CET 2005


Hello,

I would like to suggest a new method decorator: abstractmethod. I'm
definitely not the only one who've thought about it, but I discussed
this on c.l.py, and came to think that it's a nice idea. An even
Pythonic!

This has nothing to do with type checking and adaptation - or, to be
more precise, it may be combined with them, but it will live happily
without them. I don't understand these issues a great deal.

What was my situations? I had to write a few classes, all with the
same interface but with a different implementation, that were meant to
work inside some infrastructure. The specific class that would be used
would be selected by what exactly the user wanted. Some methods of
these classes were exactly the same in all of the classes, so
naturally, I wrote a base class with an implementation of these
methods.

But then came the question: and what about the other methods? I wanted
to document that they should exist in all the classes of that family,
and that they should do XYZ; otherwise, they won't fit the
infrastructure. So I wrote something like:

def get_changed(self):
    """This method should return the changed keys since last call."""
    raise NotImplementedError

But I wasn't happy about it. I thought that

@abstractmethod
def get_changed(self):
    """This methods should ..."""

would have been nicer. Why?

1. "Beautiful is better than ugly." - Who was talking here about
errors? I just wanted to say what the method should do!

2. "Explicit is better than implicit." - This is really the issue. I
*meant* to declare that a method should be implemented in subclasses,
and what it should do, but I *was* actually defining a method which
raises NotImplementedError when called with no arguments. I am used to
understanding NotImplementedError as "We should really implement this
some day, when we have the time", not as "In order to be a proud
subclass of BaseClass, you should implement this method".

3. "There should be one-- and preferably only one --obvious way to do
it." - I could have written this in a few other ways:

def get_changed(self):
    """This method should return the changed keys since last call.

    PURE VIRTUAL.
    """

def get_changed(self):
    """This method should return the changed keys since last call."""
    raise NotImplementedError, "get_changed is an abstract methods.
Subclasses of BaseClass should implement it."

What's good about the last example is that when the exception occurs,
it would be easier to find the problem. What's bad about it, is that
it's completely redundent, and very long to write.

Ok. Now another thing: I want classes that contain abstractmethods be
uninstantiable. One (and the main) reason is that instantiating that
class of mine doesn't make sense. It doesn't know how to do anything
useful, and doesn't represent any consistent object that you can have
instances of. The other reason is that it will help the programmer to
find out quickly methods he forgot to implement in his subclasses. You
may say that it suits "Errors should never pass silently."

The basic reason why I think this is fitting is that abstract classes
are something which is natural when creating class hierarchies;
usually, when I write a method, all subclasses must inherit it, or
implement another version with a compatible behaviour. Sometimes there
is no standard behaviour, so all subclasses must choose the second
option.

This concept is already in use in Python's standard library today!
"basestring" was created as the base class of "str" and "unicode".
What I'm proposing is just to make this possible also in code written
in Python.

George Sakkis has posted a very nice Python implementation of this:
http://groups-beta.google.com/group/comp.lang.python/msg/597e9ffa7b1f709b

To summarize, I think that abstract methods are simply not regular
functions, since by definition they don't specify actions, and so they
deserves an object of their own. And if it helps with testing the
subclasses - then why not?


What do you say?

Noam


More information about the Python-Dev mailing list