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.
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)
)
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With