I l@ve RuBoard |
Did all of the above make sense? If not, don't worry; now that we've had a quick tour, we're going to dig a bit deeper and study the concepts we've introduced in more detail. We met the class statement in our first examples, but let's formalize some of the ideas we introduced. As in C++, the class statement is Python's main OOP tool. Unlike in C++, class isn't really a declaration; like def, class is an object builder, and an implicit assignment—when run, it generates a class object, and stores a reference to it in the name used in the header.
As we saw on our quick tour, class is a compound statement with a body of indented statements under it. In the header, superclasses are listed in parentheses after the class name, separated by commas. Listing more than one superclass leads to multiple inheritance (which we'll say more about later in this chapter):
class <name>(superclass,...): # assign to name data = value # shared class data def method(self,...): # methods self.member = value # per-instance data
Within the class statement, specially-named methods overload operators; for instance, a function called _ _ init __ is called at instance object construction time, if defined.
At the start of this chapter, we mentioned that classes are mostly just namespaces— a tool for defining names (called attributes) that export data and logic to clients. So how do you get from the statement to a namespace?
Here's how. Just as with modules, the statements nested in a class statement body create its attributes. When Python executes a class statement (not a call to a class), it runs all the statements in its body from top to bottom. Assignments that happen during this process create names in the class's local scope, which become attributes in the associated class object. Because of this, classes resemble both modules and functions:
Like functions, class statements are a local scope where names created by nested assignments live.
Like modules, names assigned in a class statement become attributes in a class object.
The main distinction for classes is that their namespaces are also the basis of inheritance in Python; attributes are fetched from other classes if not found in a class or instance object. Because class is a compound statement, any sort of statement can be nested inside its body—for instance, print, =, if, and def. As we've seen, nested defs make class methods, but other assignments make attributes too. For example, suppose we run the following class:
class Subclass(aSuperclass): # define subclass data = 'spam' # assign class attr def __init__(self, value): # assign class attr self.data = value # assign instance attr def display(self): print self.data, Subclass.data # instance, class
This class contains two defs, which bind class attributes to method functions. It also contains a = assignment statement; since the name data is assigned inside the class, it lives in the class's local scope and becomes an attribute of the class object. Like all class attributes, data is inherited and shared by all instances of the class:[2]
[2] If you've used C++, you may recognize this as similar to the notion of C++'s static class data—members that are stored in the class, independent of instances. In Python, it's nothing special: all class attributes are just names assigned in the class statement, whether they happen to reference functions (C++'s methods) or something else (C++'s members).
>>> x = Subclass(1) # make two instance objects >>> y = Subclass(2) # each has its own "data" >>> x.display(); y.display() # "self.data" differs, "Subclass.data" same 1 spam 2 spam
When we run this code, the name data lives in two places—in instance objects (created in the __ init __ constructor) and in the class they inherit names from (created by the = assignment). The class's display method prints both versions, by first qualifying the self instance, and then the class itself. Since classes are objects with attributes, we can get to their names by qualifying, even if there's no instance involved.
I l@ve RuBoard |