By Brian Fitzgerald
Here are my observations on python yield.
The presence of “yield” causes a function to become a factory of generators. Here is an example.
def fgen():
p, f = 1, 1
print('initial p=%s p=%s ' % (p, f))
while True:
print('y %s' % f)
yield f
p, f = f, p + f
print('next p=%s f=%s' % (p, f))
Now we will run it. The call:
fa = fgen()
print('g %s' % fa)
for fi in fa:
print('ret A %s' % fi)
if fi >= 5:
break
The output:
g <generator object fgen at 0x00C280C0> initial p=1 p=1 y 1 ret A 1 next p=1 f=2 y 2 ret A 2 next p=2 f=3 y 3 ret A 3 next p=3 f=5 y 5 ret A 5
Notes:
- The call fa = fgen() produced no output. No fgen code ran.
- fgen’s return type is generator. fa is a generator.
- “for i in fa:” causes the generator to iterate.
- In the first iteration, the “print(‘initial…” statement ran.
- When execution reached “yield f”, the generator returned f and returned control to the caller. That is evident from this output:
y 1 ret A 1
- On the second iteration, generator execution picked up where it left off, and ran
p, f = f, p + f
output:
next p=1 f=2
Note that f values are generated on the fly whenever the generator is called.
If the same generator (“fa”) gets used again, like this:
for fi in fa:
print('ret A+ %s' % fi)
break
then the generator picks up where it left off:
next p=5 f=8 y 8 ret A+ 8
Calling fgen again gets a new generator that starts from scratch.
fb = fgen()
print('g %s' % fb)
for fi in fb:
print('ret B %s' % fi)
if fi >= 3:
break
Output:
g <generator object fgen at 0x02DE81B0> initial p=1 p=1 y 1 ret B 1 next p=1 f=2 y 2 ret B 2 next p=2 f=3 y 3 ret B 3
Summary:
- “yield” is used to define a function that returns a generator.
- On the first call to the generator, execution runs up to the yield.
- On subsequent calls, execution continues where it left off.