Search code examples
pythonrecursioniteratorgenerator

Does Python allow a recursive __iter__ function?


I'm trying to write an __iter__ function that should traverse a directory recursively (including subdirectories), and since its structure is arbitrary, I thought a recursive function would be the way to go. But it isn't working.

Here's what I have:

class Dummy(object):

    def __init__(self, directory):
        self.directory = directory

    def _iterate_on_dir(self, path):
        '''
        Internal helper recursive function.
        '''
        for filename in os.listdir(path):
            full_path = os.path.join(path, filename)
            if os.path.isdir(full_path):
                self._iterate_on_dir(full_path)
            else:
                yield full_path

    def __iter__(self):
        '''
        Yield filenames
        '''
        return self._iterate_on_dir(self.directory)

Some print statements showed me that the recursive call is simply ignored.

How can I accomplish this?


Solution

  • Right now when you recursively call _iterate_on_dir you're just creating a generator object, not actually iterating over it.

    The fix is to yield from the generator instead of calling it:

    if os.path.isdir(full_path):
        yield from self._iterate_on_dir(full_path)
    

    Note that this syntax didn't exist in Python 2, instead it'd be:

    for thing in self._iterate_on_dir(full_path):
        yield thing