Re: [Tutor] Passing Functions or Code as Parameters

2005-10-28 Thread Kent Johnson
Ed Singleton wrote:
 On 27/10/05, Kent Johnson [EMAIL PROTECTED] wrote:
 
Ed Singleton wrote:
Can I pass a block of code that will be executed within the function's
scope?

Yes, you can define a function within traverse() and pass that function to 
things_to_do(), but I don't know how that will help.
 
 
 I was thinking more of something I think I read in Ruby where you can
 pass a block of code to a function and it will perform the block of
 code at each iteration, and you can operate within the scope of the
 function.  (I think they were actually called blocks or something).

Ruby has code blocks which are passed to a function. They are widely used in 
Ruby. The closest equivalent in Python 2.4 is to pass a function to the other 
function. This has much the same capabilities as Ruby blocks but not as natural 
a syntax.

There is a proposal to add a similar capability to Python but it has not been 
finalized - see PEP 343:
http://www.python.org/peps/pep-0343.html

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

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


[Tutor] Passing Functions or Code as Parameters

2005-10-27 Thread Ed Singleton
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:

from path import path

def traverse(directory, depth=0):
thedir = path(directory)
for item in thedir.files():
##  Do stuff relative to the depth
for item in thedir.dirs():
traverse(item,depth+1)

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?

Thanks

Ed
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Passing Functions or Code as Parameters

2005-10-27 Thread Kent Johnson
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

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Passing Functions or Code as Parameters

2005-10-27 Thread Kent Johnson
Ed Singleton wrote:
 Wow, thanks again, Kent.
 
 If my understanding of functions in Python is correct, then the
 do_something() function won't have access to the variables inside
 traverse.  Is this right?

Yes, that's right. Python is lexically scoped which means you have access to 
variables in the enclosing scopes in the actual program text, not the scope of 
the callers.
 
 I know I could pass them as parameters:
 
 def traverse(directory, things_to_do, depth=0):
 thedir = path(directory)
 for item in thedir.files():
  things_to_do(depth, item)
 for item in thedir.dirs():
 traverse(item, things_to_do, depth+1)
 
 But what if I don't know in advance what parameters I want to pass? 

You don't have very many possibilities here, maybe just pass them all? You 
could pass locals() to things_to_do() - locals() returns a dictionary 
containing all the current local variables. Then things_to_do() would take a 
single argument and extract the variables it wants.

Why do you need this much flexibility? I would just pass thedir, item and depth 
to things_to_do().

 Can I pass a block of code that will be executed within the function's
 scope?

Yes, you can define a function within traverse() and pass that function to 
things_to_do(), but I don't know how that will help.

Kent

PS Please reply on list so others can participate.

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor