[ Team LiB ] |
21.2 MethodsSince you already know about functions, you also know about methods in classes. Methods are just function objects created by def statements nested in a class statement's body. From an abstract perspective, methods provide behavior for instance objects to inherit. From a programming perspective, methods work in exactly the same way as simple functions, with one crucial exception: their first argument always receives the instance object that is the implied subject of a method call. In other words, Python automatically maps instance method calls to class method functions as follows. Method calls made through an instance: instance.method(args...) are automatically translated to class method function calls of this form: class.method(instance, args...) where the class is determined by locating the method name using Python's inheritance search procedure. In fact, both call forms are valid in Python. Beside the normal inheritance of method attribute names, the special first argument is the only real magic behind method calls. In a class method, the first argument is usually called self by convention (technically, only its position is significant, not its name). This argument provides methods with a hook back to the instance—because classes generate many instance objects, they need to use this argument to manage data that varies per instance. C++ programmers may recognize Python's self argument as similar to C++'s "this" pointer. In Python, though, self is always explicit in your code. Methods must always go through self to fetch or change attributes of the instance being processed by the current method call. This explicit nature of self is by design—the presence of this name makes it obvious that you are using attribute names in your script, not a name in the local or global scope. 21.2.1 ExampleLet's turn to an example; suppose we define the following class: class NextClass: # Define class. def printer(self, text): # Define method. self.message = text # Change instance. print self.message # Access instance. The name printer references a function object; because it's assigned in the class statement's scope, it becomes a class object attribute and is inherited by every instance made from the class. Normally, because methods like printer are designed to process instances, we call them through instances: >>> x = NextClass( ) # Make instance >>> x.printer('instance call') # Call its method instance call >>> x.message # Instance changed 'instance call' When called by qualifying an instance like this, printer is first located by inheritance, and then its self argument is automatically assigned the instance object (x); the text argument gets the string passed at the call ('instance call'). When called this way, we pass one fewer argument than it seems we need—Python automatically passes the first argument to self for us. Inside printer, the name self is used to access or set per-instance data, because it refers back to the instance currently being processed. Methods may be called in one of two ways—through an instance, or through the class itself. For example, we can also call printer by going through the class name, provided we pass an instance to the self argument explicitly: >>> NextClass.printer(x, 'class call') # Direct class call class call >>> x.message # Instance changed again 'class call' Calls routed through the instance and class have the exact same effect, as long as we pass the same instance object ourselves in the class form. By default, in fact, you get an error message if you try to call a method without any instance: >>> NextClass.printer('bad call') TypeError: unbound method printer( ) must be called with NextClass instance... 21.2.2 Calling Superclass ConstructorsMethods are normally called through instances. Calls to methods through the class, though, show up in a variety of special roles. One common scenario involves the constructor method. The __init__ method, like all attributes, is looked up by inheritance. This means that at construction time, Python locates and calls just one __init__; if subclass constructors need to guarantee that superclass construction-time logic runs too, they generally must call it explicitly through the class: class Super: def __init__(self, x): ...default code... class Sub(Super): def __init__(self, x, y): Super.__init__(self, x) # Run superclass init. ...custom code... # Do my init actions. I = Sub(1, 2) This is one of the few contexts in which your code calls an overload method directly. Naturally, you should only call the superclass constructor this way if you really want it to run—without the call, the subclass replaces it completely.[3]
21.2.3 Other Method Call PossibilitiesThis pattern of calling through a class is the general basis of extending (instead of completely replacing) inherited method behavior. In Chapter 23, we'll also meet a new option in Python 2.2, static and class methods, which allows you to code methods that do not expect an instance object in their first argument. Such methods can act like simple instance-less functions, with names that are local to the class they are coded in. This is an advanced and optional extension, though; normally, you must always pass an instance to a method, whether it is called through the instance or the class. |
[ Team LiB ] |