[Tutor] Larger program organization

Kent Johnson kent37 at tds.net
Thu Feb 17 03:40:20 CET 2005


Terry Carroll wrote:
> On Fri, 11 Feb 2005, Bob Gailer wrote:
> 
> 
>>Whenever you find yourself writing an if statement ask whether this
>>would be better handled by subclasses. Whenever you find yourself about
>>to write a global statement, consider making the variables properties of
>>a class.
> 
> 
> Bob -- 
> 
> Brian already asked for an explanation of your first statement, and I 
> found the ensuing discussion very instructive.
> 
> Can you explain the second?  As an aesthetic point, I hate globals, and 
> I'd love a discussion with some examples of using class variables as a way 
> of avoiding this.

Global variables are one way to make state persist across function calls. Here's a toy example that 
might give you the idea. Suppose you want to write a function that keeps a running total. You could 
do something like this (not recommended!):

total = 0

def addToTotal(inc):
   global total
   total += inc

Every time you call addToTotal, total is incremented.

This is already a poor design.
- There is no encapsulation - to increment the total, you call a function, to view the total you 
look at the global variable.
- There is no API - to reset the total you would have to set the global variable.

You could try to fix this by adding more functions:

def printTotal():
   print 'Total is', total

def resetTotal():
   global total
   total = 0

That's a little better, maybe. But there are other problems:
- You can only have one total. What if you want two different totals?
- Your global namespace has extra names - total, addToTotal, etc.

For short scripts this structure can work, but for larger projects it gets unwieldy. OOP to the 
rescue! How about a Total class?

class Total:
   def __init__(self):
     self.reset()

   def add(self, inc):
     self.total += inc

   def print(self):
     print 'Total is', self.total

   def reset(self):
     self.total = 0

You can use this like this:

t = Total()
t.inc(5)
t.print()
t.reset()

Now everything is wrapped up in a nice neat package. There is a clear, consistent API, no namespace 
pollution, and you have a reusable object.

You might also be interested in this essay: http://www.pycs.net/users/0000323/stories/15.html

Kent



More information about the Tutor mailing list