4.4 Methods
A def statement within a class declaration declares a method, a function that operates on instances of the class. Consider the following:
>>> class X: ... def f(self,y): return y ...
We declared a class X containing a method f. The rule is that methods can be called only for instances of the class or a subclass. When they are called, their first argument will be given a reference to the instance and their other arguments will be taken from the argument list. So method f takes two parameters: The first one, self, will be given a reference to an instance of class X. The second one will be given a value by the argument of the call.
The __init__() method shown in the preceding section is an example of a special method. There are many other special methods, and they are discussed in Chapters 14 and 15. The special methods are called when an instance is used in a special context; for example, as an operand for a binary operator.
The normal way to call a method is to use the dot operator. For example:
>>> z=X() >>> z.f(5) 5
The call instance.name(args) will call the method name declared in the class of instance and pass it the instance as its first parameter and the other args as the subsequent parameters. You use this first parameter to access the attributes of the instance.
If you are familiar with other object-oriented languages, you will notice that there are no "class methods" or "static methods" in a class definition; in other words, there are no methods that do not require a reference to a class instance. Instead, you would call functions in the module that contains the class and have them assign values to variables in the module.
Let's look at the data type of a method. If we look up a method in the class object, we get an unbound method object:
>>> X.f <unbound method X.f>
This means that it is a method, but it isn't attached to any instance of the class yet. If, however, we look it up in an instance, we get a bound method. Thus:
>>> z=X() >>> z.f <method X.f of X instance at 007DCEFC>
gives us a method object that is bound to an instance of the class X. We can call the bound instance as a function of one parameter:
>>> g=z.f >>> g(7) 7
But we cannot call the unbound method, f, as a function of one parameter. It needs two parameters, the first being an instance:
>>> g=X.f >>> g(7) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: unbound method must be called with class instance 1st argument >>> g(z,7) 7
By the way, methods are not stored in the class object as unbound methods, but rather as functions. A class object contains a special attribute, __dict__, that is a dictionary containing the namespace of the class. If you look up a method in that dictionary, you find a function. Thus:
>>> X.__dict__["f"] <function f at 007B2464>
When it looks up a function in a class object, the dot operator creates a method object. Figure 124 shows a picture of the relationships between method objects, classes, and modules.
Now, to show a use of the instance reference, consider the counter class shown in Figure 42. Instances of the counter class have an attribute, count, that starts at zero by default, or at another value specified when the object is created. The method call c.bump() will add one to c.count. The call c.bump(k) will add k to c.count. The __init__() method is called automatically when an instance of the class is created and assigns its parameter val to the count attribute of the instance. This creates the count attribute, since, like variables, attributes are created when they are first assigned a value. The val=0 parameter specifies that the default value is zero. Method bump() adds its parameter by to count and returns the new value. The default increment is specified by the parameter specification, by=1.
Figure 4-2 Counter class, file counterObj.py.
Notice, by the way, that there is no requirement that you call the first parameter of a method self. It is a custom in Python. Java and C++ programmers may prefer the name this, but many Python programmers strongly object to using anything other than self, or perhaps s for short.
Here is a test of the counter class:
>>> from counterObj import counter >>> c=counter() >>> c.count 0 >>> c.bump() 1 >>> c.count 1 >>> counter.__doc__ 'creates counter objects' >>> d=counter(3) >>> d.count 3 >>> d.bump(2) 5
Also notice that both the counterObj module and the counter class begin with string literals. These are documentation strings. You can look up these strings as the __doc__ attributes of the objects containing them:
>>> print counterObj.__doc__ counter objects: x=counter() x=counter(initVal) x.count x.bump() x.bump(increment) >>> counter.__doc__ 'creates counter objects'
You also need to distinguish between methods that are contained in classes and attributes of objects that contain functions. Here we create a function, hi(), that writes out the string "hi". Then we assign it as the bump attribute of counter object c.
>>> def hi():print "hi" ... >>> c.bump=hi >>> c.bump() hi
When we call c.bump(), we get the hi() function, not the bump method of the class. From this and the earlier discussion of bound method objects, we can see what Python does with a reference like c.bump. First it tries to find attribute bump of object c. If it finds it, it uses that. If it doesn't find an attribute with that name, Python looks in the class of object c to find a function bump. If it finds one, it creates a bound method object containing that function and the object c.
Finally, let us remark again on the scope of names in methods. In most object-oriented languages, code in a method can refer to the attributes of an object that contains it by just using the name of the attribute. In Python, it must use an explicit reference to the object, such as self, and reference the attributes with the dot operator.
So what do the variable names in the method refer to? The same as in any function, they are either local variables, global variables defined in the surrounding module, or built-in names of the Python system.1