Using Class Attributes and Static Methods


Through attributes, different objects of the same class can each have their own, unique values. You could, for example, have 10 different critters running around, each with its own name. But you may have some information that relates not to individual objects, but the entire class. You might want to, say, keep track of the total number of critters you've created. You could give each Critter object an attribute called total. But then, whenever a new object is instantiated, you'd have to update every existing object's total attribute. This would be a real pain. Fortunately, Python offers a way to create a single value that's associated with a class itself, called a class attribute. If a class is like a blueprint, then a class attribute is like a Post-it note stuck to the blueprint. There's only one copy of it, no matter how many things you make from the blueprint.

You might also find that you want a method that's associated with the class; for this, Python offers the static method. Since static methods are associated with a class, they're often used to work with class attributes.

Introducing the Classy Critter Program

No, the Classy Critter program doesn't involve a critter that went to finishing school and scoffs at other critters who don't know which fork to use. Instead, the program involves attributes and methods that belong to a class rather than a specific object. The program defines a class attribute that keeps track of the total number of Critter objects instantiated. The class also has a static method that displays this number. Figure 8.7 shows the results of the program.

click to expand
Figure 8.7: Critters are being born left and right! The program keeps track of all of them through a single, class attribute, which it displays through a static method.

Here's the program listing for Classy Critter:

 # Classy Critter # Demonstrates class attributes and static methods # Michael Dawson - 3/24/03 class Critter(object):     """A virtual pet"""     total = 0     def status():         print "\nThe total number of critters is", Critter.total     status = staticmethod(status)     def __init__(self, name):         print "A critter has been born!"         self.name = name         Critter.total += 1 #main print "Accessing the class attribute Critter.total:", print Critter.total print "\nCreating critters." crit1 = Critter("critter 1") crit2 = Critter("critter 2") crit3 = Critter("critter 3") Critter.status() print "\nAccessing the class attribute through an object:", print crit1.total raw_input("\n\nPress the enter key to exit.") 

Creating a Class Attribute

The second line in my class definition:

     total = 0 

creates a class attribute total and assigns 0 to it. Any assignment statement like this—a new variable assigned a value outside of a method—creates a class attribute. The assignment statement is executed only once, when Python first sees the class definition. This means that the class attribute exists even before a single object is created. So, you can use a class attribute without any objects of the class in existence.

Accessing a Class Attribute

Accessing a class attribute is simple. I access the new class attribute in several different places in the program. In the main part of the program, I print it with

 print Critter.total 

In the static method status(), I print the value of the Critter class attribute total with the line:

       print "\nThe total number of critters is", Critter.total 

In the constructor method, I increment the value of this class attribute through the line:

       Critter.total += 1 

As a result of this line, every time a new object is instantiated, the value of the attribute is incremented by 1.

In general, to access a class attribute, use dot notation. Type the class name, followed by a dot, followed by the attribute name.

Finally, you can access a class attribute through an object of that class. That's just what I did in the main part of the program with the following line:

 print crit1.total 

This line prints the value of the class attribute total (and not an attribute of the object itself). You can read the value of a class attribute through any object that belongs to that class. So, I could have used print crit2.total or print crit3.total and gotten the same results in this case.

TRAP

Although you can use an object of a class to access a class attribute, you can't assign a new value to a class attribute through an object. If you want to change the value of a class attribute, access it through its class name.

Creating a Static Method

The first method in the class, status(), is a method I wrote to be static. Notice that it doesn't have self in its parameter list. That's because, like all static methods, it's designed to be invoked through a class and not an object. So, the method won't be passed a reference to an object and therefore won't need a parameter, like self, to receive such a reference. Static methods can certainly list parameters, but I just didn't need any for this one.

The method definition creates a method called status(), but to actually declare it static, I wrote one more line of code:

     status = staticmethod(status) 

I passed the staticmethod() function the name of the method I want to be static, status in this case. I assigned the result to status. The name on the left side of the assignment operator is the name that the final, static method will have. After this line executes, the class has a static method, status(), which displays the total number of objects created by printing the class attribute total.

TRAP

Static methods were introduced in Python 2.2. You can't use them in an earlier version of the language. If you try, you'll get a nasty error message.

Invoking a Static Method

Invoking a static method is simple. With the first line of the main part of the program, I invoke the static method:

 Critter.status() 

As you would guess, this displays 0 since no objects have been instantiated. But notice that I'm able to invoke the method without a single object in existence. Since static methods are invoked through a class, no objects of the class need to exist before you can invoke them.

Next, I create three objects. Then, I invoke status() again, which prints a message stating that three critters exist. This works because, during the execution of the constructor method for each object, the class attribute total is increased by 1.




Python Programming for the Absolute Beginner
Python Programming for the Absolute Beginner, 3rd Edition
ISBN: 1435455002
EAN: 2147483647
Year: 2003
Pages: 194

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net