Online Book Reader

Home Category

Learning Python - Mark Lutz [355]

By Root 1425 0
in any left-to-right order we like). Again, despite its unusual name, __init__ is a normal function, supporting everything you already know about functions—including both defaults and pass-by-name keyword arguments.

When this file runs as a script, the test code at the bottom makes two instances of our class and prints two attributes of each (name and pay):

C:\misc> person.py

Bob Smith 0

Sue Jones 100000

You can also type this file’s test code at Python’s interactive prompt (assuming you import the Person class there first), but coding canned tests inside the module file like this makes it much easier to rerun them in the future.

Although this is fairly simple code, it’s already demonstrating something important. Notice that bob’s name is not sue’s, and sue’s pay is not bob’s. Each is an independent record of information. Technically, bob and sue are both namespace objects—like all class instances, they each have their own independent copy of the state information created by the class. Because each instance of a class has its own set of self attributes, classes are a natural for recording information for multiple objects this way; just like built-in types, classes serve as a sort of object factory. Other Python program structures, such as functions and modules, have no such concept.

Using Code Two Ways

As is, the test code at the bottom of the file works, but there’s a big catch—its top-level print statements run both when the file is run as a script and when it is imported as a module. This means if we ever decide to import the class in this file in order to use it somewhere else (and we will later in this chapter), we’ll see the output of its test code every time the file is imported. That’s not very good software citizenship, though: client programs probably don’t care about our internal tests and won’t want to see our output mixed in with their own.

Although we could split the test code off into a separate file, it’s often more convenient to code tests in the same file as the items to be tested. It would be better to arrange to run the test statements at the bottom only when the file is run for testing, not when the file is imported. That’s exactly what the module __name__ check is designed for, as you learned in the preceding part of this book. Here’s what this addition looks like:

# Allow this file to be imported as well as run/tested

class Person:

def __init__(self, name, job=None, pay=0):

self.name = name

self.job = job

self.pay = pay

if __name__ == '__main__': # When run for testing only

# self-test code

bob = Person('Bob Smith')

sue = Person('Sue Jones', job='dev', pay=100000)

print(bob.name, bob.pay)

print(sue.name, sue.pay)

Now, we get exactly the behavior we’re after—running the file as a top-level script tests it because its __name__ is __main__, but importing it as a library of classes later does not:

C:\misc> person.py

Bob Smith 0

Sue Jones 100000

c:\misc> python

Python 3.0.1 (r301:69561, Feb 13 2009, 20:04:18) ...

>>> import person

>>>

When imported, the file now defines the class, but does not use it. When run directly, this file creates two instances of our class as before, and prints two attributes of each; again, because each instance is an independent namespace object, the values of their attributes differ.

* * *

Version Portability Note


I’m running all the code in this chapter under Python 3.0, and using the 3.0 print function call syntax. If you run under 2.6 the code will work as-is, but you’ll notice parentheses around some output lines because the extra parentheses in prints turn multiple items into a tuple:

c:\misc> c:\python26\python person.py

('Bob Smith', 0)

('Sue Jones', 100000)

If this difference is the sort of detail that might keep you awake at nights, simply remove the parentheses to use 2.6 print statements. You can also avoid the extra parentheses portably by using formatting to yield a single object to print. Either of the following works in both 2.6 and 3.0, though the method form is newer:

print('{0} {1}'.format(bob.name,

Return Main Page Previous Page Next Page

®Online Book Reader