13.7. Binding and Method Invocation

Now we need to readdress the Python concept of binding, which is associated only with method invocation. We will first review the facts about methods. First, a method is simply a function defined as part of a class. This means that methods are class attributes (not instance attributes). Second, methods can be invoked only when there is an instance of the class in which the method was defined. When there is an instance present, the method is considered bound. Without an instance, a method is considered unbound. And third, the first argument in any method definition is the variable self, which represents the instance object which invokes the method.

CORE NOTE: What is self?

The variable self is used in class instance methods to reference the instance which the method is bound to. Because a method's instance is always passed as the first argument in any method call, self is the name that was chosen to represent the instance. You are required to put self in the method declaration (you may have noticed this already) but do not need to actually use the instance (self) within the method.

If you do not use self in your method, you might consider creating a regular function instead, unless you have a particular reason not to. After all, your code, because it does not use the instance object in any way, “unlinks” its functionality from the class, making it seem more like a general function.

We will now create a class C with a method called showSelf() which will display more information about the instance object that was just created:

>>> class C:
…        def showSelf(self):
…            self
…            type(self)
…            id(self)

>>> c = C()
>>> c.showSelf()
<__main__.C instance at 94abe0>
<type 'instance'>
9743328

Now let us take a look directly at the instance to see if the information matches—and it does:

>>> c
<__main__.C instance at 94abe0>
>>> type(c)
<type 'instance'>
>>> id(c)
9743328

In other object-oriented languages, self is named this.


13.7.1. Invoking Bound Methods

Methods, bound or not, is made up of the same code. The only difference is whether there is an instance present so that the method can be invoked. Recall that even though self is required as the first argument in every method declaration, it never needs to be passed explicitly when you invoke it from an instance. The interpreter automatically performs that task for you.

Once again, here is an example of invoking a bound method, first found in Section 13.4.2:

>>> class MyClass:
…       def myNoActionMethod(self):
…           pass
…
>>>
>>> myInstance = MyClass()            # create instance
>>> myInstance.myNoActionMethod()     # invoke method

To invoke a method, use the name of the instance and the name of the method in dotted attribute notation followed by the function operator and any arguments.

Also in Section 13.4.2, we briefly noted the failure of invoking the method with the class name. The cause of this failure is that no instance was given to the method. Without invoking a method using an instance (and having that instance passed automatically as self to the method), the interpreter complained that self was not passed in. What we did wrong was to invoke an unbound method without an instance.

13.7.2. Invoking Unbound Methods

There are generally two reasons a programmer might attempt to invoke an unbound method. One is when a programmer is trying to implement static methods (which is not supported in Python), and the other is when a specific instance of the class defining the method is not available. We begin our tale by describing a workaround to the lack of static method support in Python.

Static Method Workaround

Static methods are generally desired in two different scenarios. The first is a situation where a programmer wants to keep his or her global or local namespace “pure,” by not adding another function to the corresponding namespace. Or secondly, perhaps it is a small or insignificant function which is somehow related to the class he wants to define it in, or maybe it is a function that helps manage static data. The first case presents a relatively weak argument, but there is some merit for the latter case, this static member management function. Here, we simply want to invoke the method in a functional sense (meaning independent of instances) in order to update static data.

>>> class C:
…        version = 1.0         # static data attribute
…        def updateVersion(self, newv):
…            C.version = newv  # update static data
…

And of course, invoking this method without an instance gives us the same TypeError exception we have seen before:

>>> C.updateVersion(2.0)
Traceback (innermost last):
  File "<stdin>", line 1, in ?
    C.updateVersion()
TypeError: unbound method must be called with class
instance 1st argument

The only workaround, which may be unpleasant, is to give up and move the function to the global domain which has access to class C (and thus the attributes of C). We can obtain the desired functionality:

>>> def updateVersion(newv):
…        C.version = newv
…
>>> updateVersion(2.0)
>>> C.version
2.0

One problem with using a global function as the solution is that you do not get the “feel” that updateVersion() is a class method, because it is not. The desire is to call C.updateVersion() or something. Yes, there are other, more sinister workarounds which new Python programmers should avoid because, to paraphrase from the Python FAQ, “[if] you don't understand why you'd ever want to do this, that's because you are pure of mind, and you probably never will want to do it! This is dangerous trickery, [and] not recommended when avoidable.”

Convenient Instance Unavailable

When a bound method is invoked, for example, instance.method(x, y), the interpreter would be executing the equivalent of method(instance, x, y), as in the following example:

>>> class MyData:
…        def myMethod(self, arg):
…            print 'called myMethod with:', arg
…
>>>
>> myInstance = MyData()
>>> myInstance.myMethod('grail')
called myMethod with: grail

The call myInstance.myMethod('grail') results in the equivalent call of myMethod(myInstance, 'grail'), which matches the function signature, myMethod(self, arg).

However, invoking an unbound method does not work quite as well. Since there is no bound instance, the method call will fail because the call would be simply method(x, y) rather than method(instance, x, y). Here is the error one more time:

>>> MyData.myMethod(932)
Traceback (innermost last):
  File "<stdin>", line 1, in ?
    MyData.myMethod(932)
TypeError: unbound method must be called with class
instance 1st argument

Notice that the TypeError exception states, “unbound method must be called with class instance 1st argument.” Ah, that's the problem. The first argument passed to the method was an integer, not a class instance. The function signatures did not match, i.e., myMethod(932) versus myMethod(self, arg). What if we did pass an instance as the first argument (to make the signatures match)?

>>> MyData.myMethod(myInstance, 932)
called myMethod with: 932

Presto! It now works. So an interesting result of having an instance is that you can now invoke an unbound method if you explicitly provide the instance so that the call is method(instance, x, y).

This is all rather nice, but what if there is no instance nearby for us to use? What if in the above example, we had not created the myInstance object? Well, then we would not have been able to invoke myMethod() then. Does this ever happen? The answer is yes and comes into play in Section 13.9 below. Such situations require the invocation of a base class method from the method of a derived class. We've already seen it once, in the “Creating a Subclass” subsection of Section 13.1.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset