Speak and Shout

Tuesday, December 12, 2006

Abstract methods in Python

Following up one of my previous posts, I've been looking at code from Pygame Extended to get ideas for a Scene class to use with my Asteroids game. I'm requiring derived classes to override a process_events function in my Scene class, since each scene will need its own event loop.

In this case, it thought it would be good to have a way to specify that process_events was an abstract method. I guess I hadn't thought about abstract methods too much before in Python since I don't typically use inheritance, but I knew there wasn't anything like the notion of interfaces built into the language itself.

I started looking through the Python Cookbook for ideas and came across this article. Yikes! I wasn't sure I wanted to bother with metaclasses just for this feature. But in the comments I saw that someone else suggested raising an exception in the base class so that calling the method at runtime would fail unless there was an override.

I slapped my forehead after reading the Cookbook comment. Of course, in hindsight, it was obvious. But apparently it isn't obvious to other folks either. The pygext source code simply uses empty methods like the following:

class Foo(object):
   def update(self):
      pass # Override me in derived class


Of course, you can't distinguish pure virtual methods from regular virtual methods this way.

Even some very respectable folks have solved this problem differently: Peter Norvig, when writing his Python code for his Artificial Intelligence book, uses a made-up keyword called "abstract" which fails at runtime if it hasn't been overridden in a derived class. Not the most elegant solution either.

I really think handling abstract methods should be done at object creation like the previously mentioned Cookbook recipe does, but it should be built into Python itself. This may be one of the reasons people think OOP in Python is a hack ...

Labels: , , ,