What does the “yield” keyword do in Python?

In Python, the yield keyword is used to create a generator function, which produces a sequence of values lazily (on-demand) instead of returning them all at once. It allows you to pause and resume the function’s execution, retaining its state between successive calls. This is especially useful for handling large datasets or infinite sequences efficiently.

Key Behaviors of yield:

  1. Lazy Evaluation: Values are generated one at a time, reducing memory usage.
  2. State Preservation: The function’s state (variables, execution point) is saved between yield calls.
  3. Iteration Support: Generators implement the iterator protocol and work with loops (fornext()).

Example 1: Simple Generator

python

def count_up_to(n):
    count = 1
    while count <= n:
        yield count  # Pauses here and returns `count`
        count += 1

# Create a generator object
generator = count_up_to(3)

# Iterate using next()
print(next(generator))  # Output: 1
print(next(generator))  # Output: 2
print(next(generator))  # Output: 3
# print(next(generator))  # Raises StopIteration

# Or use in a loop
for num in count_up_to(5):
    print(num)  # Output: 1, 2, 3, 4, 5

Example 2: Infinite Sequence

Generators can model infinite sequences without memory overhead:

python

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

# Print the first 5 Fibonacci numbers
fib_gen = fibonacci()
for _ in range(5):
    print(next(fib_gen))  # Output: 0, 1, 1, 2, 3

Example 3: Sending Values to a Generator

Use send() to pass values back into the generator:

python

def echo():
    response = yield "Ready?"  # Yield initial message and wait for input
    while True:
        response = yield f"You said: {response}"

gen = echo()
print(next(gen))         # Output: "Ready?"
print(gen.send("Hello")) # Output: "You said: Hello"
print(gen.send("Bye"))   # Output: "You said: Bye"

Key Use Cases:

  • Large Data Processing: Stream data without loading it all into memory.
  • Stateful Iteration: Maintain context between iterations (e.g., parsers, pipelines).
  • Coroutines: Implement cooperative multitasking (e.g., with asyncio).

How It Works:

  1. When a generator function is called, it returns a generator object (but doesn’t execute immediately).
  2. On calling next() or send(), the function runs until it hits yield, emits a value, and pauses.
  3. The next call resumes execution immediately after the yield statement.

Comparison with return:

yieldreturn
Produces a generatorTerminates function
Can yield multiple valuesReturns once
Retains state between callsResets state

By leveraging yield, you write memory-efficient, scalable code for sequential data processing.

Leave a Reply

Your email address will not be published. Required fields are marked *