I'm writing a geometry package, with Points and Lines and Circles and so on, and eventually I want to be able to draw these things on the screen. I have two options so far for how to accomplish this, but neither of them sits quite right with me, and I'd like the opinion of comp.lang.python's wizened elders.
Option 1. Subclassing. The most Pythonic way would seem to be writing subclasses for the things I want to display, adding a ".draw(...)" method to each one, like this: class DrawablePoint( geometry.Point ): class draw( self, ... ): ... When the time comes to draw things, I'll have some list of objects I want drawn, and say for x in to_draw: x.draw(...) I see a problem with this, though. The intersection of two lines is (usually) an object of type Point. Since DrawableLine inherits from Line, this means that unless I redefine the "intersect" method in DrawableLine, the intersection of two DrawableLines will be a Point object, not a DrawablePoint. I don't want to saddle the user with the burden of converting every method output into its corresponding Drawable subclass, and I don't want to redefine every method to return an instance of said subclass. I see no other options if I continue down the subclassing path. Am I missing something? Option 2. A "draw" function, with a function dictionary. This feels weird, but is fairly simple to write, use, and extend. We have a module with a "draw_functions" dictionary that maps types onto functions, and a "draw" function that just looks up the proper type in the dictionary and calls the corresponding function. If you create your own object, you can just add a new entry to the dictionary. The implementation is simple enough to outline here: In file "geometry/gui.py": def draw_point(...): ... def draw_line(...): ... draw_functions = {geometry.Point: draw_point, geometry.Line: draw_line, ...} def draw( x, *args, **kwargs ): for type, callback in draw_functions.iteritems(): if isinstance(x, type): callback(x, *args, **kwargs) else: raise TypeError("don't know how to draw things of type " "{0}".format(type(x))) In the file that uses this: # Drawing a predefined type of object: geometry.gui.draw(some_point, ...) # Here we define a new kind of object and tell the package how to draw it. class MyObject(GeometricObject): ... def draw_my_object(...): ... geometry.gui.draw_functions[MyObject] = draw_my_object # And now we draw it. geometry.gui.draw(MyObject(...), ...) If I feel fancy, I might use a decorator for adding entries to draw_functions, but this is basically how it'd work. The second way feels kludgey to me, but I'm leaning towards it because it seems like so much less work and I'm out of ideas. Can anyone help, explaining either a different way to do it or why one of these isn't as bad as I think? Thanks for your time! -Spencer -- http://mail.python.org/mailman/listinfo/python-list