Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yield in a recursive function

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?

like image 549
Ali Avatar asked Jul 20 '11 00:07

Ali


People also ask

What is yield from in python?

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.

What happens when a recursive function returns?

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.

What are the 3 parts that make a function recursive?

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.

What are the four basic rules of recursion?

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.


1 Answers

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.

like image 182
Jeremy Avatar answered Oct 15 '22 14:10

Jeremy