Home > Articles > Open Source > Python

  • Print
  • + Share This
This chapter is from the book

Built-in Types for Representing Program Structure

In Python, functions, classes, and modules are all objects that can be manipulated as data. Table 3.9 shows types that are used to represent various elements of a program itself.

Table 3.9 Built-in Python Types for Program Structure

Type Category

Type Name

Description

Callable

types.BuiltinFunctionType

Built-in function or method

type

Type of built-in types and classes

object

Ancestor of all types and classes

types.FunctionType

User-defined function

types.MethodType

Class method

Modules

types.ModuleType

Module

Classes

object

Ancestor of all types and classes

Types

type

Type of built-in types and classes

Note that object and type appear twice in Table 3.9 because classes and types are both callable as a function.

Callable Types

Callable types represent objects that support the function call operation. There are several flavors of objects with this property, including user-defined functions, built-in functions, instance methods, and classes.

User-Defined Functions

User-defined functions are callable objects created at the module level by using the def statement or with the lambda operator. Here’s an example:

def foo(x,y):
    return x + y

bar = lambda x,y: x + y

A user-defined function f has the following attributes:

Attribute(s)

Description

f.__doc__

Documentation string

f.__name__

Function name

f.__dict__

Dictionary containing function attributes

f.__code__

Byte-compiled code

f.__defaults__

Tuple containing the default arguments

f.__globals__

Dictionary defining the global namespace

f.__closure__

Tuple containing data related to nested scopes

In older versions of Python 2, many of the preceding attributes had names such as func_code, func_defaults, and so on. The attribute names listed are compatible with Python 2.6 and Python 3.

Methods

Methods are functions that are defined inside a class definition. There are three common types of methods—instance methods, class methods, and static methods:

class Foo(object):
    def instance_method(self,arg):
        statements
    @classmethod
    def class_method(cls,arg):
        statements
    @staticmethod
    def static_method(arg):
        statements

An instance method is a method that operates on an instance belonging to a given class. The instance is passed to the method as the first argument, which is called self by convention. A class method operates on the class itself as an object. The class object is passed to a class method in the first argument, cls. A static method is a just a function that happens to be packaged inside a class. It does not receive an instance or a class object as a first argument.

Both instance and class methods are represented by a special object of type types.MethodType. However, understanding this special type requires a careful understanding of how object attribute lookup (.) works. The process of looking something up on an object (.) is always a separate operation from that of making a function call. When you invoke a method, both operations occur, but as distinct steps. This example illustrates the process of invoking f.instance_method(arg) on an instance of Foo in the preceding listing:

f = Foo()                 # Create an instance
meth = f.instance_method  # Lookup the method and notice the lack of ()
meth(37)                  # Now call the method

In this example, meth is known as a bound method. A bound method is a callable object that wraps both a function (the method) and an associated instance. When you call a bound method, the instance is passed to the method as the first parameter (self). Thus, meth in the example can be viewed as a method call that is primed and ready to go but which has not been invoked using the function call operator ().

Method lookup can also occur on the class itself. For example:

umeth = Foo.instance_method   # Lookup instance_method on Foo
umeth(f,37)                   # Call it, but explicitly supply self

In this example, umeth is known as an unbound method. An unbound method is a callable object that wraps the method function, but which expects an instance of the proper type to be passed as the first argument. In the example, we have passed f, a an instance of Foo, as the first argument. If you pass the wrong kind of object, you get a TypeError. For example:

>>> umeth("hello",5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor 'instance_method' requires a 'Foo' object but received a
'str'
>>>

For user-defined classes, bound and unbound methods are both represented as an object of type types.MethodType, which is nothing more than a thin wrapper around an ordinary function object. The following attributes are defined for method objects:

Attribute

Description

m.__doc__

Documentation string

m.__name__

Method name

m.__class__

Class in which this method was defined

m.__func__

Function object implementing the method

m.__self__

Instance associated with the method (None if unbound)

One subtle feature of Python 3 is that unbound methods are no longer wrapped by a types.MethodType object. If you access Foo.instance_method as shown in earlier examples, you simply obtain the raw function object that implements the method. Moreover, you’ll find that there is no longer any type checking on the self parameter.

Built-in Functions and Methods

The object types.BuiltinFunctionType is used to represent functions and methods implemented in C and C++. The following attributes are available for built-in methods:

Attribute

Description

b.__doc__

Documentation string

b.__name__

Function/method name

b.__self__

Instance associated with the method (if bound)

For built-in functions such as len(), __self__ is set to None, indicating that the function isn’t bound to any specific object. For built-in methods such as x.append, where x is a list object, __self__ is set to x.

Classes and Instances as Callables

Class objects and instances also operate as callable objects. A class object is created by the class statement and is called as a function in order to create new instances. In this case, the arguments to the function are passed to the __init__() method of the class in order to initialize the newly created instance. An instance can emulate a function if it defines a special method, __call__(). If this method is defined for an instance, x, then x(args) invokes the method x.__call__(args).

Classes, Types, and Instances

When you define a class, the class definition normally produces an object of type type. Here’s an example:

>>> class Foo(object):
...    pass
...
>>> type(Foo)
<type 'type'>

The following table shows commonly used attributes of a type object t:

Attribute

Description

t.__doc__

Documentation string

t.__name__

Class name

t.__bases__

Tuple of base classes

t.__dict__

Dictionary holding class methods and variables

t.__module__

Module name in which the class is defined

t.__abstractmethods__

Set of abstract method names (may be undefined if there aren’t any)

When an object instance is created, the type of the instance is the class that defined it. Here’s an example:

>>> f = Foo()
>>> type(f)
<class '__main__.Foo'>

The following table shows special attributes of an instance i:

Attribute

Description

i.__class__

Class to which the instance belongs

i.__dict__

Dictionary holding instance data

The __dict__ attribute is normally where all of the data associated with an instance is stored. When you make assignments such as i.attr = value, the value is stored here. However, if a user-defined class uses __slots__, a more efficient internal representation is used and instances will not have a __dict__ attribute. More details on objects and the organization of the Python object system can be found in Chapter 7.

Modules

The module type is a container that holds objects loaded with the import statement. When the statement import foo appears in a program, for example, the name foo is assigned to the corresponding module object. Modules define a namespace that’s implemented using a dictionary accessible in the attribute __dict__. Whenever an attribute of a module is referenced (using the dot operator), it’s translated into a dictionary lookup. For example, m.x is equivalent to m.__dict__["x"]. Likewise, assignment to an attribute such as m.x = y is equivalent to m.__dict__["x"] = y. The following attributes are available:

Attribute

Description

m.__dict__

Dictionary associated with the module

m.__doc__

Module documentation string

m.__name__

Name of the module

m.__file__

File from which the module was loaded

m.__path__

Fully qualified package name, only defined when the module object refers to a package

  • + Share This
  • 🔖 Save To Your Account