How about "pure virtual methods"?
Noam Raphael
noamr at remove.the.dot.myrea.lbox.com
Sat Dec 25 17:57:56 EST 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