How yield catches StopIteration exception?

前端 未结 5 594
陌清茗
陌清茗 2020-12-08 04:54

Why in the example function terminates:

def func(iterable):
    while True:
        val = next(iterable)
        yield val

but if I take of

5条回答
  •  一个人的身影
    2020-12-08 05:09

    When a function contains yield, calling it does not actually execute anything, it merely creates a generator object. Only iterating over this object will execute the code. So my guess is that you're merely calling the function, which means the function doesn't raise StopIteration because it is never being executed.

    Given your function, and an iterable:

    def func(iterable):
        while True:
            val = next(iterable)
            yield val
    
    iterable = iter([1, 2, 3])
    

    This is the wrong way to call it:

    func(iterable)
    

    This is the right way:

    for item in func(iterable):
        # do something with item
    

    You could also store the generator in a variable and call next() on it (or iterate over it in some other way):

    gen = func(iterable)
    print(next(gen))   # prints 1
    print(next(gen))   # prints 2
    print(next(gen))   # prints 3
    print(next(gen))   # StopIteration
    

    By the way, a better way to write your function is as follows:

    def func(iterable):
        for item in iterable:
            yield item
    

    Or in Python 3.3 and later:

    def func(iterable):
        yield from iter(iterable)
    

    Of course, real generators are rarely so trivial. :-)

提交回复
热议问题