Python Generator Methods
Generator methods let a caller control a paused generator.
Send a value in
Priming means starting the generator. It now waits at the first yield.
def echo():
message = yield "waiting"
yield message
gen = echo()
print(next(gen))
print(gen.send("hello"))What send() gives back
send() does two jobs at once. The value goes in and the next yield comes out.
def running_total():
total = 0
while True:
value = yield total
total += value
gen = running_total()
print(next(gen))
print(gen.send(5))
print(gen.send(7))Raise inside with throw()
throw() raises at the paused yield line. The generator can catch that error.
def careful():
try:
yield 1
yield 2
except ValueError:
yield "caught it"
gen = careful()
print(next(gen))
print(gen.throw(ValueError))Close it with close()
close() raises GeneratorExit inside. Clean up there and do not yield again.
def tidy():
try:
yield 1
yield 2
except GeneratorExit:
print("cleaning up")
raise
gen = tidy()
print(next(gen))
gen.close()
try:
next(gen)
except StopIteration:
print("closed")Delegate with yield from
yield from passes every value out. The small generator does the work.
def letters():
yield "a"
yield "b"
def outer():
yield from letters()
yield "c"
print(list(outer()))Example
def running_average():
total = 0.0
count = 0
average = None
while True:
value = yield average
total += value
count += 1
average = total / count
averages = running_average()
next(averages)
print(averages.send(10))
print(averages.send(20))
print(averages.send(30))
print(averages.send(40))Key points
- Priming: run next() once so the generator waits at its first yield
- Use send(value) to resume a generator and feed a value in
- send() returns the next value the generator yields
- Use throw(type) to raise an error inside the generator
- Use close() to stop a generator early
- GeneratorExit: the signal close() raises inside the generator
- Use yield from to delegate to a sub-generator and pass its values out
- These methods control a generator while it sits paused.
In this example, running_average waits at yield. The first next() call primes it. That call gets None as the starting average. Each send() call then feeds one new number in. The generator adds the number to total. It adds one to count. It then works out the new average. The yield sends that average back out. The four prints show the average after each new number.
Note
In Python, send() on a fresh generator can only send None.
Prime it first with next().
Try it Yourself
Edit the code, then press Run.
Running is simulated · Python Playground
Exercise
You want to send 10 into a fresh generator. What must you do first?