Online Book Reader

Home Category

Learning Python - Mark Lutz [411]

By Root 1771 0
the class and never through an instance. That is, Python 3.0 will pass along an instance to methods only for through-instance calls. When calling through a class, you must pass an instance manually only if the method expects one:

C:\misc> c:\python30\python

>>> class Selfless:

... def __init__(self, data):

... self.data = data

... def selfless(arg1, arg2): # A simple function in 3.0

... return arg1 + arg2

... def normal(self, arg1, arg2): # Instance expected when called

... return self.data + arg1 + arg2

...

>>> X = Selfless(2)

>>> X.normal(3, 4) # Instance passed to self automatically

9

>>> Selfless.normal(X, 3, 4) # self expected by method: pass manually

9

>>> Selfless.selfless(3, 4) # No instance: works in 3.0, fails in 2.6!

7

The last test in this fails in 2.6, because unbound methods require an instance to be passed by default; it works in 3.0 because such methods are treated as simple functions not requiring an instance. Although this removes some potential error trapping in 3.0 (what if a programmer accidentally forgets to pass an instance?), it allows class methods to be used as simple functions as long as they are not passed and do not expect a “self” instance argument.

The following two calls still fail in both 3.0 and 2.6, though—the first (calling through an instance) automatically passes an instance to a method that does not expect one, while the second (calling through a class) does not pass an instance to a method that does expect one:

>>> X.selfless(3, 4)

TypeError: selfless() takes exactly 2 positional arguments (3 given)

>>> Selfless.normal(3, 4)

TypeError: normal() takes exactly 3 positional arguments (2 given)

Because of this change, the staticmethod decorator described in the next chapter is not needed in 3.0 for methods without a self argument that are called only through the class name, and never through an instance—such methods are run as simple functions, without receiving an instance argument. In 2.6, such calls are errors unless an instance is passed manually (more on static methods in the next chapter).

It’s important to be aware of the differences in behavior in 3.0, but bound methods are generally more important from a practical perspective anyway. Because they pair together the instance and function in a single object, they can be treated as callables generically. The next section demonstrates what this means in code.

* * *

Note


For a more visual illustration of unbound method treatment in Python 3.0 and 2.6, see also the lister.py example in the multiple inheritance section later in this chapter. Its classes print the value of methods fetched from both instances and classes, in both versions of Python.

* * *

Bound Methods and Other Callable Objects

As mentioned earlier, bound methods can be processed as generic objects, just like simple functions—they can be passed around a program arbitrarily. Moreover, because bound methods combine both a function and an instance in a single package, they can be treated like any other callable object and require no special syntax when invoked. The following, for example, stores four bound method objects in a list and calls them later with normal call expressions:

>>> class Number:

... def __init__(self, base):

... self.base = base

... def double(self):

... return self.base * 2

... def triple(self):

... return self.base * 3

...

>>> x = Number(2) # Class instance objects

>>> y = Number(3) # State + methods

>>> z = Number(4)

>>> x.double() # Normal immediate calls

4

>>> acts = [x.double, y.double, y.triple, z.double] # List of bound methods

>>> for act in acts: # Calls are deferred

... print(act()) # Call as though functions

...

4

6

9

8

Like simple functions, bound method objects have introspection information of their own, including attributes that give access to the instance object and method function they pair. Calling the bound method simply dispatches the pair:

>>> bound = x.double

>>> bound.__self__, bound.__func__

(<__main__.Number object at 0x0278F610>,

®Online Book Reader