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 -- http://mail.python.org/mailman/listinfo/python-list