I have met a snippet of Python 3 code:
def gen():
try:
while True:
yield 1
finally:
print("stop")
print(next(gen()))
After I run it, I thought at first that the output should be:
1
But actually the result is:
stop
1
How can this happen? What happened under the hood?
If I run for i in gen(): print(i)
, there will be an infinite loop which is what I expected. What is the difference between for
and next
here?
The finally clause is being executed on garbage collection of the generator object.
Consider the following two scenarios:
def gen():
try:
while True:
yield 1
finally:
print("stop")
g1 = gen(); print('first time')
print(next(g1))
g2 = gen(); print('second time') # no stop will be printed because we haven't hit the finally clause yet
def gen():
try:
while True:
yield 1
finally:
print("stop")
g = gen(); print('first time')
print(next(g))
g = gen(); print('second time') # stop will be printed when the first object g was assigned to is garbage collected
The loop terminates when the generator is closed, which happens automatically if you don't save a reference to it. Once that happens, the try
statement guarantees that the finally
block is executed before the generator object is garbage collected. Compare:
>>> next(gen())
stop
1
with
>>> x = gen()
>>> next(x)
1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With