'How to transform a generator function into an iterator object in python?

Often generator functions are simpler to write than iterators, e.g. consider this example generator function

def generator_fn():
    x = 0
    for y in range(10):
         x += y
         yield x

Is there a straightforward way to transform an arbitrary generator function into an iterator object, i.e.,

class IteratorFromGenerator(object):

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

    def __iter__(self):
        # ???
        pass

    def __next__(self):
        # ???
        pass

To me this seems favorable but impossible. Favorable, because generator functions are often simpler to write and require less code. Usually, I begin writing generator functions and at some point, I need an iterator object (e.g. when generator_fn is a member of my class Foo and I want to write for x in my_foo instead of for x in my_foo.generator_fn(). Impossible, because generator functions define the execution flow of the loop process, while iterator objects simply offer their __next__ interface to be requested by an undefined "outer" execution flow.

Am I right or is there a possibility to do this?

Of course, apart from the trivial, memory-consuming solution of consuming all generated elements into a list.

Thanks for any help.



Solution 1:[1]

A function with yield is a function that, when called, returns an instance of a generator object (which is a specific type of iterator). So, as already mentioned in the comments, you only have to do:

def generator_fn():
    x = 0
    for y in range(10):
         x += y
         yield x

iterator_from_generator_fn = generator_fn()

However, by doing this, you will probably encounter this problem: Resetting generator object in Python, because by definition, you can only iterate over a generator once.

What you probably want is an iterable : an object which __iter__ method returns an iterator object. Something like this :

class IterableFromGenerator(object):

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

    def __iter__(self):
        return generator_fn()


iterable_from_generator_fn = IterableFromGenerator(generator_fn)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1