How about "pure virtual methods"?

Noam Raphael noamr at remove.the.dot.myrea.lbox.com
Sat Dec 25 23:57:56 CET 2004


Thank you very much for this answer! I learned from you about unit 
tests, and you convinced me that "testing oriented programming" is a 
great way to program.

You made me understand that indeed, proper unit testing solves my 
practical problem - how to make sure that all the methods which should 
be implemented were implemented. However, I'm still convinced that this 
feature should be added to Python, for what may be called "aesthetic 
reasons" - I came to think that it fills a gap in Python's "logic", and 
is not really an additional, optional feature. And, of course, there are 
practical advantages to adding it.

The reason why this feature is missing, is that Python supports building 
a class hierarchy. And, even in this dynamically-typed language, the 
fact that B is a subclass of A means that B is supposed to implement the 
interface of A. If you want to arrange in a class hierarchy a set of 
classes, which all implement the same interface but don't have a common 
concrete class, you reach the concept of an "abstract class", which 
can't be instantiated. And the basestring class is exactly that.

The current Python doesn't really support this concept. You can write in 
the __new__ of such a class something like "if cls == MyAbstractClass: 
raise TypeError", but I consider this as a patch - for example, if you 
have a subclass of this class which is abstract too, you'll have to 
write this exception code again. Before introducing another problem, let 
me quote Alex:

> ... If you WANT the method in the ABC, for documentation
> purposes, well then, that's not duplication of code, it's documentation,
> which IS fine (just like it's quite OK to have some of the same info in
> a Tutorial document, in a Reference one, AND in a class's docstring!).
> 
> If you don't want to have the duplication your unit tests become easier:
> you just getattr from the class (don't even have to bother instantiating
> it, ain't it great!), and check the result with inspect.

That's actually right - listing a method which should be implemented by 
subclasses, in the class definition is mainly a matter of 
*documentation*. I like the idea that good documentation can be derived 
from my documented code automatically, and even if I provide an external 
documentation, the idea that the code should explain itself is a good 
one. The problem is, that the current convention is not a good 
documentation:

   def frambozzle(self):
      ''' must make the instance frambozzled '''
      raise NotImplementedError

The basic problem is that, if you take this basic structure, it already 
means another thing: This is a method, which takes no arguments and 
raises a NotImplementedError. This may mean, by convention, that this 
method must be implemented by subclasses, but it may also mean that this 
method *may* be implemented by subclasses. I claim that a declaration 
that a method must be implemented by subclass is simply not a method, 
and since Python's "logic" does lead to this kind of thing, it should 
supply this object (I think it should be the class "abstract"). Two of 
Python's principles are "explicit is better than implicit", and "there 
should be (only?) one obvious way to do it". Well, I think that this:

@abstract
def frambozzle(self):
     """Must make the instance frambozzled"""
     pass

is better than the previous example, and from

def frambozzle(self):
     raise NotImplementedError, "You must implemented this method, and 
it must make the instance frambozzled"

and from

def frambozzle(self):
     """Must make the instance frambozzled.

     PURE VIRTUAL
     """
     pass

and from maybe other possible conventions. Note also that making this 
explicit will help you write your tests, even if Python would allow 
instantiation of classes which contain abstract methods - you will be 
able to simple test "assert not isinstance(MyClass.frambozzle, abstract)".
(I don't like the solution of not mentioning the method at all, which 
makes the test equally simple, because it doesn't document what the 
method should do in the class definition, and I do like in-code 
documentation.)

To summarize, I think that this feature should be added to Python 
because currently, there's no proper way to write some code which fits 
the "Python way". As a bonus, it will help you find errors even when 
your unit tests are not sufficient.

I plan to raise this issue in python-dev. If you have any additional 
comments, please post them here. (I will probably be able to reply only 
by the weekend.)

Have a good day,
Noam



More information about the Python-list mailing list