Returning generator from a function
Question: I'm slowly getting to wrap my head around Python generators.

While it's not a real life problem for now, I'm still wondering why I can't
return a generator from a function.

When I define a function with `yield`, it acts as a generator. But if I define
it _inside_ another function and try to return that instead, I get an ordinary
function, i.e. not a generator with `next` method.

In other words, why the `give_gen()` approach in code below does not work?

    
    
    #!/usr/bin/python
    
    import time
    
    def gen(d):
        n = 0
        while True:
            n = n + d
            time.sleep(0.5)
            yield n
    
    def give_gen(d):
        def fn():
            n = 0
            while True:
                n = n + d
                time.sleep(0.5)
                yield n
        return fn
    
    if __name__ == '__main__':
    
        g = give_gen(3)     # does not work
        g = gen(3)          # works well
    
        while True:
            print g.next()
            # AttributeError: 'function' object has no attribute 'next'
            # in case of give_gen
    

Why can't I return a generator from a function?


Answer: A generator function returns a generator _only when called_. Call `fn` to
create the generator object:

    
    
    return fn()
    

or call the returned object:

    
    
    g = give_gen(3)()
    

You _did_ call `gen()`; had you referred to _just_ `gen` without calling it
you'd have a reference to that function.

