Python Introspection

Introduction

  • Everything in Python is an object.
  • Introspection is code looking at other modules and functions in memory as objects, information about them and manipulating them.

Example: The if name trick allows this program do something useful when run by itself, without interfering with its use as a module for other programs. In this case, the program simply prints out the doc string of the info function.

def info(object, spacing=10, collapse=1): #1 2 
    """Print methods and doc strings.
 
    Takes module, class, list, dictionary, or string."""
    methodList = [method for method in dir(object) if callable(getattr(object, method))]
    processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
    print "\n".join(["%s %s" %
                      (method.ljust(spacing),
                       processFunc(str(getattr(object, method).__doc__)))
                     for method in methodList])
 
if __name__ == "__main__":                #3 
    print info.__doc__
  1. This module has one function, info. According to its function declaration, it takes three parameters: object, spacing, and collapse. The last two are actually optional parameters.
  2. The info function has a multi-line doc string that succinctly describes the function's purpose. Note that no return value is mentioned; this function will be used solely for its effects, rather than its value.
  3. The if name trick allows this program do something useful when run by itself, without interfering with its use as a module for other programs. In this case, the program simply prints out the doc string of the info function.

Optional and Named Arguments

  • Python allows default values for function arguments, if the function is called without the argument, the argument gets its default value.

Example

def info(object, spacing=10, collapse=1):
# Valid calls
info(odbchelper)                    #1
info(odbchelper, 12)                #2
info(odbchelper, collapse=0)        #3
info(spacing=15, object=odbchelper) #4
  1. With only one argument, spacing gets its default value of 10 and collapse gets its default value of 1.
  2. With two arguments, collapse gets its default value of 1.
  3. Here you are naming the collapse argument explicitly and specifying its value. spacing still gets its default value of 10.
  4. Even required arguments (like object, which has no default value) can be named, and named arguments can appear in any order

Built-In Functions

The type Function

  • Returns the datatype of any arbitrary object.
  • It takes anything and returns its datatype.

Example

>>> type(1)           
<type 'int'>
>>> li = []
>>> type(li)          
<type 'list'>
>>> import odbchelper
>>> type(odbchelper)  
<type 'module'>
>>> import types      
>>> type(odbchelper) == types.ModuleType
True

The str Function

  • The str converts data into a string. Every datatype can be converted into a string.

Example

>>> str(1)          
'1'
>>> horsemen = ['war', 'pestilence', 'famine']
>>> horsemen
['war', 'pestilence', 'famine']
>>> horsemen.append('Powerbuilder')
>>> str(horsemen)   
"['war', 'pestilence', 'famine', 'Powerbuilder']"
>>> str(odbchelper) 
"<module 'odbchelper' from 'c:\\docbook\\dip\\py\\odbchelper.py'>"
>>> str(None)       
'None'

dir Function

  • dir returns a list of the attributes and methods of any object.
>>> li = []
>>> dir(li)           #1
['append', 'count', 'extend', 'index', 'insert',
'pop', 'remove', 'reverse', 'sort']
>>> d = {}
>>> dir(d)            #2
['clear', 'copy', 'get', 'has_key', 'items', 'keys', 'setdefault', 'update', 'values']
>>> import odbchelper
>>> dir(odbchelper)   #3
['__builtins__', '__doc__', '__file__', '__name__', 'buildConnectionString']
  1. li is a list, so dir(li) returns a list of all the methods of a list. Note that the returned list contains the names of the methods as strings, not the methods themselves.
  2. d is a dictionary, so dir(d) returns a list of the names of dictionary methods.
  3. odbchelper is a module, so dir(odbchelper) returns a list of all kinds of stuff defined in the module, including built-in attributes, like name, doc, and whatever other attributes and methods you define.

callable function

  • The callable function takes any object and returns True if the object can be called, or False otherwise.
>>> import string
>>> string.punctuation           #1
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
>>> string.join                 #2
<function join at 00C55A7C>
>>> callable(string.punctuation) #3
False
>>> callable(string.join)        #4
True
>>> print string.join.__doc__    #5
join(list [,sep]) -> string
  1. The functions in the string module are deprecated (although many people still use the join function), but the module contains a lot of useful constants like this string.punctuation, which contains all the standard punctuation characters.
  2. string.join is a function that joins a list of strings.
  3. string.punctuation is not callable; it is a string. (A string does have callable methods, but the string itself is not callable.)
  4. string.join is callable; it's a function that takes two arguments.
  5. Any callable object may have a doc string. By using the callable function on each of an object's attributes, you can determine which attributes you care about (methods, functions, classes) and which you want to ignore (constants and so on) without knowing anything about the object ahead of time.

Getting Object References

  • You can get a reference to a function without knowing its name until run-time, by using the getattr function.
  • A common usage pattern of {{getattr} is as a dispatcher.

Filtering Lists

  • A filter expression can be any expression that evaluates true or false. Any element for which the filter epxression evaluates true will be included in the mapping.

lambda Functions

  • A lambda function is a function that takes any number of arguments (including optional arguments) and returns the value of a single expression.
  • one-line mini-functions on the fly.
  • These functions are anonymous, they are not bound to a name at runtime.
  • The entire function can only be one expression.
  • The function has no name, but it can be called through the variable it is assigned to.
  • If we need a function only once and it's quite simple, it's more convenient to use a lambda construct to generate a (temporary) anonymous function.

Example: Compute prime numbers

>>> nums = range(2, 50) 
>>> for i in range(2, 8): 
...     nums = filter(lambda x: x == i or x % i, nums)
... 
>>> print nums
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

Example: You can mix default and required variables. Notice there is a default on list, but since it is defined in the middle of the list, you can't do this: fold_right( lambda x y: x + y, 0 )

def fold_right( fun, list=[], base ):
    if list == []:
        return base
    else:
        return fun( list[0], fold_right( fun, list[1:], base ) )
 
# Now, let's say I want to just define fun and base, and not list.
# I could do this:
fold_right( fun = lambda x y: x + y, base = 0) #Look 'ma, no list!
 
# This makes sense if you have a large argument list (5, 10, + variables),
# some default and some required.  You can easily specify just the
# variables necessary to run the function and leave the defaults alone.
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.