I am trying to do something to all the files under a given path. I don't want to collect all the file names beforehand then do something with them, so I tried this:
import os import stat def explore(p): s = '' list = os.listdir(p) for a in list: path = p + '/' + a stat_info = os.lstat(path ) if stat.S_ISDIR(stat_info.st_mode): explore(path) else: yield path if __name__ == "__main__": for x in explore('.'): print '-->', x
But this code skips over directories when it hits them, instead of yielding their contents. What am I doing wrong?
Yield is a keyword in Python that is used to return from a function without destroying the states of its local variable and when the function is called, the execution starts from the last yield statement. Any function that contains a yield keyword is termed a generator.
With recursion, we are waiting for return values coming from other execution contexts. These other contexts are higher up the stack. When the last item on the stack finishes execution, that context generates a return value. This return value gets passed down as a return value from the recursive case to the next item.
A recursive case has three components: divide the problem into one or more simpler or smaller parts of the problem, call the function (recursively) on each part, and. combine the solutions of the parts into a solution for the problem.
Like the robots of Asimov, all recursive algorithms must obey three important laws: A recursive algorithm must call itself, recursively. A recursive algorithm must have a base case. A recursive algorithm must change its state and move toward the base case.
Iterators do not work recursively like that. You have to re-yield each result, by replacing
explore(path)
with something like
for value in explore(path): yield value
Python 3.3 added the syntax yield from X
, as proposed in PEP 380, to serve this purpose. With it you can do this instead:
yield from explore(path)
If you're using generators as coroutines, this syntax also supports the use of generator.send()
to pass values back into the recursively-invoked generators. The simple for
loop above would not.
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