Python generators
send function
Python programming
generator functions
Python iterators

What is the purpose of the send function on Python generators?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Most Python developers use generators only as lazy iterators with yield and next(). The send() method adds a second channel: it lets the caller push a value back into the paused generator. That turns a generator from a one-way producer into a small coroutine-like state machine.

What send() Actually Does

When a generator is paused at a yield expression, calling send(value) resumes execution and makes that yield expression evaluate to value.

Basic example:

python
1def echo():
2    received = yield "ready"
3    yield f"got: {received}"
4
5
6g = echo()
7print(next(g))          # ready
8print(g.send("hello"))  # got: hello

The important detail is that the value sent by send() is received inside the generator where execution was suspended.

Why send(None) or next() Comes First

You cannot send a real value into a generator before it reaches the first yield. The generator has to be “primed” first.

python
1def counter():
2    increment = yield 0
3    while True:
4        increment = 1 if increment is None else increment
5        increment = yield increment
6
7
8g = counter()
9print(next(g))  # or g.send(None)

If you call g.send(5) immediately on a fresh generator, Python raises TypeError because there is no paused yield ready to receive the value yet.

Two-Way Communication Pattern

send() is useful when the generator should react to caller input while maintaining internal state.

python
1def accumulator():
2    total = 0
3    while True:
4        value = yield total
5        if value is not None:
6            total += value
7
8
9g = accumulator()
10print(next(g))       # 0
11print(g.send(5))     # 5
12print(g.send(10))    # 15
13print(g.send(None))  # 15

This is more expressive than repeatedly rebuilding state in external code because the generator owns its own internal state transitions.

Historical Coroutine Use

Before async and await, Python used generator-based coroutines heavily. send() was central to that style because it allowed event loops and schedulers to push values back into paused computations.

A simplified coroutine-style example:

python
1def greeter():
2    name = yield "Who are you?"
3    yield f"Hello, {name}"
4
5
6g = greeter()
7question = next(g)
8print(question)
9answer = g.send("Ava")
10print(answer)

Today, native async def is usually a better abstraction for real asynchronous workflows, but understanding send() helps explain older coroutine libraries and Python’s evolution.

Relationship to throw() and close()

Generators also support throw() and close(), which complete the control surface around paused execution:

  • 'send(value) injects a normal value.'
  • 'throw(exc) injects an exception.'
  • 'close() requests termination.'

Together, these methods make generators programmable suspension points rather than simple iterators.

When send() Is the Right Tool

Use send() when:

  • the generator maintains internal state.
  • the caller needs to influence the next step of computation.
  • you are implementing or reading coroutine-like logic.

Avoid it when a normal function, iterator, or class would be clearer. send() is powerful, but it also makes control flow less obvious to casual readers.

Common Pitfalls

  • Calling send(value) before priming the generator with next() or send(None).
  • Forgetting that the value is delivered into the paused yield expression.
  • Using send() where a simple function or object would be easier to read.
  • Confusing generator-based coroutines with modern async and await.
  • Ignoring StopIteration handling when the generator completes.

Summary

  • 'send() lets callers push values back into a paused generator.'
  • It turns generators into two-way stateful computations, not just lazy iterators.
  • A generator must be primed before receiving a non-None value.
  • 'send() was foundational for older coroutine patterns in Python.'
  • Use it when two-way control flow is genuinely helpful, not just because it exists.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.