A question beginners sometimes ask is, "Should I use classes in my program?" This article gives some ideas of when it is appropriate to introduce classes into a design. One of the great things about Python is that it supports several styles of programming. A really simple program might start out as straight-line code without even any functions. As it gets more complicated you break it up into functions to keep it readable or to reuse bits of code. You may put some functions together in a module. Many of the Python library modules are written like this, without any use of classes. This approach works well for many relatively simple needs. On the other hand, some kinds of complexity are best addressed with classes. Here are some indications that you should start using classes, with illustrations taken from the Python standard library modules. More than one copy of the same state variablesMaybe you decided to put your shared state into global variables instead of creating a class. The single client of your module works great. But what if you have a second client that needs its own copy of the module state, or you need to use the module from multiple threads? You are getting wacky results as the module trips over itself trying to serve two masters. How can you have two copies of the global state? Move it into a class! Each client has its own instance of the class with its own state. Each separate instance of a class has its own state, independent of the other instances. For example, a DOM tree built with the xml.dom module may contain many Element objects, each with its own state. This wouldn't be possible without class instances to hold the data. To extend the behavior of an existing classThis is classic OOP. Maybe there is an existing class that does almost what you want. You just need to add a little something and it will be perfect. Or maybe a library class is intended to be subclassed in normal use. Make a class which subclasses the class you want to change, and add the new behavior to it.
Some library classes are meant to be extended. For example unittest.TestCase is routinely subclassed to make new test cases. cmd.Cmd must be subclassed to be useful. Widget classes in GUI frameworks are commonly subclassed. A callback function needs persistent stateThis is a special situation that comes up pretty regularly for me. For example, I have a database access module with a query method. The query method takes a callback function as an argument. For each row returned by the query, the callback function is called. Now suppose I want to build a list with all the query rows. I can make a class that holds the list. The class has a __call__ method. This makes instances of the class act like functions. I pass an instance of the class to the query function. The instance accumulates the list which I pull out at the end: class Callback: def __init__(self): self.vals = [] def __call__(self, row): # This is the actual callback self.vals.append(row) The client code looks like this: callback = Callback() db.query(sql, callback) result = callback.vals Note: This could also be done with a closure like this: result = [] def callback(row): result.append(row) db.query(sql, callback) FinallyI have just scratched the surface of object-oriented design. My intent is help beginners understand when it might be appropriate to use classes, not to catalog every possible use. I have linked to the documentation pages for the modules I use as examples. If you have Python installed, you can find the source code in the Python library directory. On Windows look in C:Python23Lib. last change 2004-10-25 20:49:04 |
When should a program use classes and objects? BlogRoll |
© 2004, Kent Johnson