Section 14.1. Callable Objects


14.1. Callable Objects

A number of Python objects are what we describe as "callable," meaning any object that 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 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.

14.1.1. Functions

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

Built-in Functions (BIFs)

BIFs are functions written in C/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.

BIFs have the basic type attributes, but some of the more interesting unique ones are listed in Table 14.1.

Table 14.1. Built-in Function Attributes

BIF Attribute

Description

bif.__doc__

Documentation string (or None)

bif.__name__

Function name as a string

bif.__self__

Set to None (reserved for built-in methods)

bif.__module__

Name of the module where bif is defined (or None)


You can list all attributes of a function by using dir():

    >>> dir(type)     ['__call__', '__class__', '__cmp__', '__delattr__', '__doc__',     '__getattribute__', '__hash__', '__init__', '__module__',     '__name__', '__new__', '__reduce__', '__reduce_ex__',     '__repr__', '__self__', '__setattr__', '__str__']


Internally, BIFs are represented as the same type as built-in methods (BIMs), so invoking type() on a BIF or BIM results in:

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


Note that this does not apply to factory functions, where type() correctly returns the type of object produced:

     >>> type(int)      <type 'type'>      >>> type(type)      <type 'type'>


User-Defined Functions (UDFs)

UDFs are generally written in Python and 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, and due to the nested scopes improvement in 2.2, we now have access to attributes in multiply-nested scopes. Hooks to attributes defined elsewhere are provided by the func_closure attribute.

Like the BIFs above, UDFs also have many attributes. The more interesting and specific ones to UDFs are listed below 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

udf.func_dict

Namespace for function attributes

udf.func_doc

(See udf.__doc__above)

udf.func_name

(See udf.__name__above)

udf.func_closure

Tuple of Cell objects (see the Python/C API Reference Manual) that contains references to free variables (those used in udf but defined elsewhere; see the Python [Language] Reference Manual)


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 codes that 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() factory 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 us take a quick look at UDF names, using lambdaFunc above and foo from the preceding subsection:

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


As we noted back in Section 11.9, programmers can also define function attributes once the function has been declared (and a function object available). All of the new attributes become part of the udf.__dict__ object. Later on in this chapter, we will discuss taking strings of Python code and executing it. There will be a combined example toward the end of the chapter highlighting function attributes and dynamic evaluation of Python code (from strings) and executing those statements.

14.1.2. Methods

In Chapter 13 we discovered methods, functions that are defined as part of a classthese 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.

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


Built-in Methods (BIMs)

We discussed in the previous section how built-in methods are similar to built-in functions. Only builtin types (BITs) have BIMs. As you can see below, the type() factory function gives the same output for built-in methods as it does for BIFsnote 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):

Recall that for classes and instances, their data and method attributes can be obtained by using the dir() BIF with that object as the argument to dir(). It can also be used with BIMs:

    >>> dir([].append)     ['__call__', '__class__', '__cmp__', '__delattr__', '__doc__',     '__getattribute__', '__hash__', '__init__', '__module__',     '__name__', '__new__', '__reduce__', '__reduce_ex__',     '__repr__', '__self__', '__setattr__', '__str__']


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 Chapter 13, 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(object):             # define class     ...      def foo(self): pass     # define UDM     ...     >>> c = C()                      # instantiation     >>> type(C)                      # type of class     <type 'type'>     >>> type(c)                      # type of instance     <class '__main__.C'>     >>> type(C.foo)                 # type of unbound method     <type 'instancemethod'>     >>> type(c.foo)                 # type of bound method     <type 'instancemethod'>


UDMs have attributes as shown in Table 14.4.

Table 14.4. User-Defined Method Attributes

UDM Attribute

Description

udm.__doc__

Documentation string (same as udm.im_func.__doc__)

udm.__name__

Method name as a string (same as udm.im_func.__name__)

udm.__module__

Name of the module where udm is defined (or None)

udm.im_class

Class that method is associated with (for bound methods; if unbound, then the class that requested udm)

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     <bound method C.foo of <__main__.C object at 0x00B42DD0>     >>> c                  # instance foo()'s bound to     <__main__.C object at 0x00B42DD0>


14.1.3. 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 that 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(object):        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.

14.1.4. Class Instances

Python provides the __call__() special method for classes, which allows a programmer to create objects (instances) that 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 argumentsimply 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). Here we present an example of a callable instance, using a similar example as in the previous section:

     >>> class C(object):      ...   def __call__(self, *args):      ...     print "I'm callable! Called with args:\n", args      ...      >>> c = C()                        # instantiation      >>> c                              # our instance      <__main__.C instance at 0x00B42DD0>      >>> callable(c)                    # instance is callable      True      >>> 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.



Core Python Programming
Core Python Programming (2nd Edition)
ISBN: 0132269937
EAN: 2147483647
Year: 2004
Pages: 334
Authors: Wesley J Chun

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net