Generators and nested functions

Edward C. Jones edcjones at erols.com
Sat Jan 26 11:21:41 EST 2002


Thanks. Here is a variant which also yields the original "top" directory:

def walk_gen(top):
     yield top
     if not os.path.isdir(top):
         return
     names = os.listdir(top)
     for name in names:
         fullname = os.path.join(top, name)
         for name2 in walk_gen(fullname):
             yield name2

I think a generator like this should be put in os.path. Are there other 
generators that are so useful that they need to be in official Python? 
Perhaps depth-first traversal of nested lists.

Steven Majewski wrote:

> 
> On Fri, 25 Jan 2002, Edward C. Jones wrote:
> 
> 
>>The following code would be a simple way for doing a useful thing except
>>that it doesn't work. Why not? Any easy fixes?
>>
>>from __future__ import generators
>>import os
>>
>>def walk_dirs(startdir):
>>     def visit(arg, dirname, names):
>>	yield dirname
>>
>>     os.path.walk(startdir, visit, None)
>>
>>if __name__ == '__main__':
>>     for dir in walk_dirs('/some/small/directory'):
>>	print dir
>>
>>
> 
> Replace the line 'yield dirname' with 'print dirname' and run,
> and you'll see what's going on. The visit function doesn't
> need to return a value -- it needs to have side effects.
> os.path.walk is throwing away any return values, so there's
> no way for your "yield" to get thru.
> 
> Programming with callback function always seems a bit inside-out
> to me, which is one of the reasons I like generators for this
> sort of path walking.
> 
> For a generator version, try something like:
> 
> 
>>>>def files(start):
>>>>
> ...     for x in os.listdir(start):
> ...             x = os.path.join( start, x )
> ...             yield x
> ...             if os.path.isdir( x ):
> ...                     for y in files(x): yield(y)
> ...
> 
>>>>for f in files('.') : print f
>>>>
> 
> 
> With os.path.walk, if you want to trim or filter the files, you need
> to do it in the visit function. With a generator version, you can
> filter the output of the generator. ( However, trimming branches
> that you shouldn't follow is a trickier problem! )
> 
> For another method of composing generators see:
> <http://groups.google.com/groups?q=generators+group:comp.lang.python+author:Majewski&hl=en&scoring=d&as_drrb=b&as_mind=12&as_minm=1&as_miny=2001&as_maxd=20&as_maxm=12&as_maxy=2001&rnum=1&selm=mailman.1008090197.6318.python-list%40python.org>
> 
> which lets you compose filters and generators to do something like:
> 
> for x in Files() & isGif & fileOwner('sdm7g') & fileLargerThan(512):
> 	do_something_with(x)
> 
> 
> -- Steve Majewski






More information about the Python-list mailing list