To understand how the multiple objects idea works, you have to first understand that there are two kinds of objects in Python's OOP model class objects and instance objects. Class objects provide default behavior and serve as factories for instance objects. Instance objects are the real objects your programs process; each is a namespace in its own right, but inherits (i.e., has automatic access to) names in the class it was created from. Class objects come from statements, and instances from calls; each time you call a class, you get a new instance of that class. This object generation concept is very different from any of the other program constructs we've seen so far in this book. In effect, classes are factories for making many instances. By contrast, there is only one copy of each module imported (in fact, this is one reason that we have to call reload, to update the single module object). Next, we'll summarize the bare essentials of Python OOP. Classes are in some ways similar to both def and modules, but they may be quite different than what you're used to in other languages. 20.1.1 Class Objects Provide Default Behavior
20.1.2 Instance Objects Are Concrete Items
20.1.3 A First ExampleLet's turn to a real example to show how these ideas work in practice. To begin, let's define a class named FirstClass, by running a Python class statement interactively: >>> class FirstClass: # Define a class object. ... def setdata(self, value): # Define class methods. ... self.data = value # self is the instance. ... def display(self): ... print self.data # self.data: per instance We're working interactively here, but typically, such a statement would be run when the module file it is coded in is imported. Like functions, your class won't even exist until Python reaches and runs this statement. Like all compound statements, class starts with a header line that lists the class name, followed by a body of one or more nested and (usually) indented statements. Here, the nested statements are defs; they define functions that implement the behavior the class means to export. As we've learned, def is really an assignment; here, it assigns to the names setdata and display in the class statement's scope, and so generates attributes attached to the class: FirstClass.setdata, and FirstClass.display. Functions inside a class are usually called methods; they're normal defs, but the first argument automatically receives an implied instance object when called the subject of a call. We need a couple of instances to see how: >>> x = FirstClass( ) # Make two instances. >>> y = FirstClass( ) # Each is a new namespace. By calling the class this way (notice the parenthesis), it generates instance objects, which are just namespaces that have access to their class's attributes. Properly speaking, at this point we have three objects two instances and a class. Really, we have three linked namespaces, as sketched in Figure 20-1. In OOP terms, we say that x "is a" FirstClass, as is y. Figure 20-1. Classes and instances are linked namespace objects![]() The two instances start empty, but have links back to the class they were generated from. If we qualify an instance with the name of an attribute that lives in the class object, Python fetches the name from the class by inheritance search (unless it also lives in the instance): >>> x.setdata("King Arthur") # Call methods: self is x >>> y.setdata(3.14159) # Runs: FirstClass.setdata(y, 3.14159) Neither x nor y has a setdata of its own; instead, Python follows the link from instance to class if an attribute doesn't exist in an instance. And that's about all there is to inheritance in Python: it happens at attribute qualification time, and just involves looking up names in linked objects (e.g., by following the is-a links in Figure 20-1). In the setdata function inside FirstClass, the value passed in is assigned to self.data. Within a method, self the name given to the leftmost argument by convention automatically refers to the instance being processed (x or y), so the assignments store values in the instances' namespaces, not the class (that's how the data names in Figure 20-1 are created). Since classes generate multiple instances, methods must go through the self argument to get to the instance to be processed. When we call the class's display method to print self.data, we see that it's different in each instance; on the other hand, display is the same in x and y, since it comes (is inherited) from the class: >>> x.display( ) # self.data differs in each. King Arthur >>> y.display( ) 3.14159 Notice that we stored different object types in the data member (a string and a floating-point). Like everything else in Python, there are no declarations for instance attributes (sometimes called members); they spring into existence the first time they are assigned a value, just like simple variables. In fact, we can change instance attributes either in the class itself by assigning to self in methods, or outside the class by assigning to an explicit instance object: >>> x.data = "New value" # Can get/set attributes >>> x.display( ) # outside the class too. New value Although less common, we could even generate a brand new atribute on the instance, by assigning to its name outside the class's method functions: >>> x.anothername = "spam" # Can get/set attributes This would attach a new attribute called anothername to the instance object x, which may or may not be used by any of the class's methods. Classes usually create all the instance's attributes by assignment to the self argument, but they don't have to; programs can fetch, change, or create attributes on any object that they have a reference to. |