< BACKMake Note | BookmarkCONTINUE >
156135250194107072078175030179198180025031194137176049106218111004228147163053241134031082

Callable Objects

A number of Python objects are what we describe as "callable," meaning any object which can be invoked with the function operator "()". The function operator is placed immediately following the name of the callable to invoke it. For example, the function "foo" is called with "foo()". You already know this. Callables may also be invoked via functional programming interfaces such as apply(), filter(), map(), and reduce(), all of which we discussed in Chapter 11. Python has four callable objects: functions, methods, classes, and some class instances. Keep in mind that any additional references or aliases of these objects are callable, too.

Functions

The first callable object we introduced was the function. There are three types of different function objects, the first being the Python built-in functions.

Built-in Functions (BIFs)

BIFs are generally written as extensions in C or C++, compiled into the Python interpreter, and loaded into the system as part of the first (built-in) namespace. As mentioned in previous chapters, these functions are found in the __builtin__ module and are imported into the interpreter as the __builtins__ module. In restricted execution modes, only a subset of these functions is available. (See Section 14.6 for more details on restricted execution.)

All BIFs come with the attributes given in Table 14.1.

Table 14.1. Built-in Function Attributes
BIF Attribute Description
bif.__doc__ documentation string
bif.__name__ function name as a string
bif.__self__ set to None (reserved for built-in methods)

You can verify these attributes by using the dir() built-in function, as indicated below using the type() BIF as our example:

							
>>> dir(type)
['__doc__', '__name__', '__self__']

						

Internally, built-in functions are represented as the same type as built-in methods, so invoking the type() built-in function on a built-in function or method outputs "builtin_function_or_method," as indicated in the following example:

							
>>> type(type)
<type 'builtin_function_or_method'>

						
User-defined Functions (UDFs)

The second type of function is the user-defined function. These are generally defined at the top-level part of a module and hence are loaded as part of the global namespace (once the built-in namespace has been established). Functions may also be defined in other functions; however, the function at the innermost level does not have access to the containing function's local scope. As indicated in previous chapters, Python currently supports only two scopes: the global scope and a function's local scope. All the names defined in a function, including parameters, are part of the local namespace.

All UDFs come with the attributes listed in Table 14.2.

Table 14.2. User-defined Function Attributes
UDF Attribute Description
udf.__doc__ documentation string (also udf.func_doc)
udf.__name__ function name as a string (also udf.func_name)
udf.func_code byte-compiled code object
udf.func_defaults default argument tuple
udf.func_globals global namespace dictionary; same as calling globals(x) from within function

Internally, user-defined functions are of the type "function," as indicated in the following example by using type():

							
>>> def foo(): pass
>>> type(foo)
<type 'function'>

						
lambda Expressions (Functions named "<lambda>")

Lambda expressions are the same as user-defined functions with some minor differences. Although they yield function objects, lambda expressions are not created with the def statement and instead are created using the lambda keyword.

Because lambda expressions do not provide the infrastructure for naming the code which are tied to them, lambda expressions must be called either through functional programming interfaces or have their reference be assigned to a variable, and then they can be invoked directly or again via functional programming. This variable is merely an alias and is not the function object's name.

Function objects created by lambda also share all the same attributes as user-defined functions, with the only exception resulting from the fact that they are not named; the __name__ or func_name attribute is given the string "<lambda>".

Using the type() built-in function, we show that lambda expressions yield the same function objects as user-defined functions:

							
>>> lambdaFunc = lambda x: x * 2
>>> lambdaFunc(100)
200
>>> type(lambdaFunc)
<type 'function'>

						

In the example above, we assign the expression to an alias. We can also invoke type() directly on a lambda expression:

							
>>> type (lambda: 1)
<type 'function'>

						

Let's take a quick look at UDF names, using lambdaFunc above and foo from the preceding subsection:

							
>>> foo.__name__
'foo'
>>> lambdaFunc.__name__
'<lambda>'

						

Methods

In the previous chapter, we discovered methods, functions which are defined as part of a class—these are user-defined methods. Many Python data types such as lists and dictionaries also have methods, known as built-in methods. To further show this type of "ownership," methods are named with or represented alongside the object's name via the dotted-attribute notation.

Built-in Methods (BIMs)

We discussed in the previous section how built-in methods are similar to built-in functions. Only built-in types (BITs) have BIMs. As you can see below, the type() built-in function gives the same output for built-in methods as it does for built-in functions—note how we have to provide a built-in type (object or reference) in order to access a BIM:

							
>>> type([].append)
<type 'builtin_function_or_method'>

						

Furthermore, both BIMs and BIFs share the same attributes, too. The only exception is that now the __self__ attribute points to a Python object (for BIMs) as opposed to None (for BIFs):

Table 14.3. Built-in Method Attributes
BIM Attribute Description
bim.__doc__ documentation string
bim.__name__ function name as a string
bim.__self__ object the method is bound to

By convention, a BIT should have the following lists of its BIMs and (built-in) attributes.

Table 14.4. Built-in Type Attributes
BIT Attribute Description
bit.__methods__ list of (built-in) methods
bit.__members__ list of (built-in) data attributes

Recall that for classes and instances, their data and method attributes can be obtained by using the dir() built-in function with that object as the argument to dir(). Apparently, BITs have two attributes that list their data and method attributes. Attributes of BITs may be accessed with either a reference or an actual object, as in these examples:

							
>>> aList = ['on', 'air']
>>> aList.append('velocity')
>>> aList
['on', 'air', 'velocity']
>>> aList.insert(2, 'speed')
>>> aList
['on', 'air', 'speed', 'velocity']
>>>
>>> [].__methods__
['append', 'count', 'extend', 'index', 'insert', 'pop',
'remove', 'reverse', 'sort']
>>> [3, 'headed', 'knight'].pop()
'knight'

						

It does not take too long to discover, however, that using an actual object to access its methods does not prove very useful functionally, as in the last example. No reference is saved to the object, so it is immediately garbage-collected. The only thing useful you can do with this type of access is to use it to display what methods (or members) a BIT has.

User-defined Methods (UDMs)

User-defined methods are contained in class definitions and are merely "wrappers" around standard functions, applicable only to the class they are defined for. They may also be called by subclass instances if not overridden in the subclass definition.

As explained in the previous chapter, UDMs are associated with class objects (unbound methods), but can be invoked only with class instances (bound methods). Regardless of whether they are bound or not, all UDMs are of the same type, "instance method," as seen in the following calls to type():

							
>>> class C:                               # define class
…        def foo(self): pass               # define UDM
…
>>> c = C()                                # instantiation
>>> type(C.foo)                            # type of unbound method
<type 'instance method'>
>>> type(c.foo)                            # type of bound method
<type 'instance method'>

						

UDMs have the following attributes:

Table 14.5. User-defined Method Attributes
UDM Attribute Description
udm.__doc__ documentation string
udm.__name__ method name as a string
udm.im_class class which method is associated with
udm.im_func function object for method (see UDFs)
udm.im_self associated instance if bound, None if unbound

Accessing the object itself will reveal whether you are referring to a bound or an unbound method. As you can also see below, a bound method reveals to which instance object a method is bound:

							
>>> C.foo                         # unbound method object
<unbound method C.foo>
>>>
>>> c.foo                         # bound method object
<method C.foo of C instance at 122c78>
>>> c                             # instance foo()'s bound to
<__main__.c instance at 122c78>

						

Classes

The callable property of classes allows instances to be created. "Invoking" a class has the effect of creating an instance, better known as instantiation. Classes have default constructors which perform no action, basically consisting of a pass statement. The programmer may choose to customize the instantiation process by implementing an __init__() method. Any arguments to an instantiation call are passed on to the constructor:

						
>>> class C:
    def __init__(self, *args):
      print 'instantiated with these arguments:\n', args

>>> c1 = C()            # invoking class to instantiate c1
instantiated with these arguments:
()
>>> c2 = C('The number of the counting shall be', 3)
instantiated with these arguments:
('The number of the counting shall be', 3)

					

We are already familiar with the instantiation process and how it is accomplished, so we will keep this section brief. What is new, however, is how to make instances callable.

Class Instances

Python provides the __call__() special method for classes which allows a programmer to create objects (instances) which are callable. By default, the __call__() method is not implemented, meaning that most instances are not callable. However, if this method is overridden in a class definition, instances of such a class are made callable. Calling such instance objects is equivalent to invoking the __call__() method. Naturally, any arguments given in the instance call are passed as arguments to __call__().

You also have to keep in mind that __call__() is still a method, so the instance object itself is passed in as the first argument to __call__() as self. In other words, if foo is an instance, then foo() has the same effect as foo.__call__(foo)—the occurrence of foo as an argument—simply the reference to self that is automatically part of every method call. If __call__() has arguments, i.e., __call__(self, arg), then foo(arg) is the same as invoking foo.__call__(foo, arg). We present below an example of a callable instance, using a similar example to the previous section:

						
>>> class C:
…       def __call__(self, *args):
…           print "I'm callable!  Called with args:\n", args
…

>>> c = C()                             # instantiation
>>> c                                   # our instance
<__main__.C instance at babd30>
>>> callable(c)                         # instance is callable
1
>>> c()                                 # instance invoked
I'm callable!  Called with arguments:
()
>>> c(3)                                # invoked with 1 arg
I'm callable!  Called with arguments:
(3,)
>>> c(3, 'no more, no less')            # invoked with 2 args
I'm callable!  Called with arguments:
(3, 'no more, no less')

					

We close this subsection with a note that class instances cannot be made callable unless the __call__() method is implemented as part of the class definition.


Last updated on 9/14/2001
Core Python Programming, © 2002 Prentice Hall PTR

< BACKMake Note | BookmarkCONTINUE >

© 2002, O'Reilly & Associates, Inc.