[Tutor] Passing Functions or Code as Parameters

Kent Johnson kent37 at tds.net
Thu Oct 27 15:28:56 CEST 2005


Ed Singleton wrote:
> How can I pass a block of code to a function for it to perform within itself?
> 
> For example, I wrote a small function that recurses through a
> directory structure but keeps a track of the depth:
> 
> What I want to do is something like:
> 
> from path import path
> 
> def traverse(directory, depth=0, things_to_do()):
>     thedir = path(directory)
>     for item in thedir.files():
>         things_to_do(depth)
>     for item in thedir.dirs():
>         traverse(item,depth+1)
> 
> Is this possible?

Easy, actually! You almost have it.

Functions are 'first-class objects' in Python. What that means is that a function is an object as much as a list or an integer. When you define a function, you are actually binding the function object to the name you use in the def. For example:

 >>> def printer(x):
 ...   print x
 ...
 >>> printer
<function printer at 0x00A3CAF0>

The name 'printer' is now bound to a function object.

Functions can be bound to other names or passed as parameters to functions (or stored in lists, or...). Here is a function that takes a function as a parameter and calls the passed-in function several times:

 >>> def test(fn):
 ...   for x in [1, 2, 10]:
 ...     fn(x)

To call this function with the printer function as a parameter is just like any other function call:

 >>> test(printer)
1
2
10

So in your case, just remove the excess parens in your function definition. (You have to reorder the params since keyword params have to follow non-keyword params):
def traverse(directory, things_to_do, depth=0):

Then define your things_to_do function (which can be called whatever you want) as a function of one argument:

def do_something(depth):
  print depth

and call traverse passing this as an argument:

traverse(myDir, do_something)

You also have to change the recursive call to traverse(), you must pass the things_to_do parameter:

    for item in thedir.dirs():
        traverse(item,things_to_do,depth+1)

By the way this is a very powerful capability of Python. Your usage is a good example of customizing the behaviour of a function by passing another function as a parameter. You can also build lists or dicts of dispatch functions, wrap functions to modify their behaviour, etc...

Kent
-- 
http://www.kentsjohnson.com



More information about the Tutor mailing list