Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: lazy iterating through directory-like structure

I'd like to apply a function through a directory-like structure. As Python 3 supports lazy generators, I thought about using these to lazy evaluate the resulting list. This was my approach:

iterate = lambda func, d: (func(f) for f in listDir(d) if not f.isDir) + sum((iterate(func, d + f.name) for f in listDir(d) if f.isDir.), [])

This leads to unsupported operand type(s) for +: 'generator' and 'list'. Is there an idiomatic way to express this with lazy generators?

listDir accepts a path and returns a list of file information.

like image 302
Sebastian Wagner Avatar asked Feb 07 '26 18:02

Sebastian Wagner


1 Answers

Supposing that the order isn't important, I think it would typically be written:

def iterate(func, d):
    for f in listDir(d):
        if f.isDir:
            yield from iterate(func, d + f.name)
        else:
            yield func(f)

yield from only exists from Python 3.3, before that you can do:

for x in iterate(func, d + f.name):
    yield x

If you do need to string generators together, then itertools.chain and itertools.chain.from_iterator are the standard tools for the job:

def iterate(func, d):
    return itertools.chain(
        (func(f) for f in listDir(d) if not f.isDir),
        itertools.chain.from_iterable(
            iterate(func, d + f.name) for f in listDir(d) if f.isDir)
        )
    )
like image 169
Steve Jessop Avatar answered Feb 09 '26 10:02

Steve Jessop