yield
def test(): for i in 'abc': yield i for i in [1, 2, 3]: yield i if __name__ == '__main__': gen = test() print(gen.send(None)) print(gen.send(None)) print(gen.send(None)) print(gen.send(None)) print(gen.send(None)) print(gen.send(None)) print(gen.send(None))
def test(): for i in 'abc': yield i for i in [1, 2, 3]: yield i if __name__ == '__main__': gen = test() for i in gen: print(i)
Use the for loop generator because the for loop can catch StopIteration exceptions.
yield from
The above code can also be implemented with yield from
def test(): yield from 'abc' yield from [1, 2, 3] if __name__ == '__main__': gen = test() for i in test(): print(i)
What needs to be added after yield from is an iteratable object. It can be a normal iteratable object, an iterator, or even a generator.
Using yield from to implement real-time calculator
def average_gen(): """ //Child generator """ average = 0 total = 0 count = 0 while True: num = yield average if num is None: break count += 1 total += num average = total / count return average, count, total def proxy_gen(): """ //Delegation generator """ while True: average, count, total = yield from average_gen() print(f'average value{average}, Calculation{count}second, The sum{total}') def client(): """ //Call end """ calc_average = proxy_gen() calc_average.send(None) # next(calc_average) # Pre activation process print(calc_average.send(10)) print(calc_average.send(20)) print(calc_average.send(30)) calc_average.send(None) # Close association if __name__ == '__main__': client()
In the delegation generator, when true can be replaced with a for loop. The size of the loop determines the number of times that the caller can call "average. Send (none) (the first pre activation is also included).
while True and for loops are used to catch StopIteration exceptions. You can see the first piece of code.
Example
def average_gen(): """ //Child generator """ average = 0 total = 0 count = 0 while True: num = yield average if num is None: break count += 1 total += num average = total / count return average, count, total def proxy_gen(): """ //Delegation generator """ for i in range(2): average, count, total = yield from average_gen() print(f'average value{average}, Calculation{count}second, The sum{total}') def client(): """ //Call end """ calc_average = proxy_gen() calc_average.send(None) # next(calc_average) # Pre activation process print(calc_average.send(10)) print(calc_average.send(20)) print(calc_average.send(30)) calc_average.send(None) # Close association print(calc_average.send(10)) print(calc_average.send(20)) print(calc_average.send(30)) calc_average.send(None) if __name__ == '__main__': client()
The example finally throws a StopIteration exception.
Because the for loop catches an exception in the second call and enters the last one. When the call for average.send (none), for cannot loop again and cannot handle the StopIteration exception, so it is thrown.