Python generators are a powerful and memory-efficient way to create iterators. They allow you to generate a sequence of values over time, rather than computing them all at once and storing them in memory.
Generators are special functions that return an iterator object. Unlike regular functions that return a value and terminate, generators use the yield
keyword to produce a series of values over multiple calls.
To create a generator, you define a function with the yield
statement instead of return
. Here's a simple example:
def count_up_to(n):
i = 1
while i <= n:
yield i
i += 1
# Using the generator
for number in count_up_to(5):
print(number)
This generator function will produce numbers from 1 to 5, one at a time.
Similar to Python List Comprehension, generator expressions provide a concise way to create generators:
squares = (x**2 for x in range(10))
for square in squares:
print(square)
This creates a generator that yields the squares of numbers from 0 to 9.
Generators can receive values using the send()
method:
def echo_generator():
while True:
value = yield
print(f"Received: {value}")
gen = echo_generator()
next(gen) # Prime the generator
gen.send("Hello")
gen.send("World")
Generators can be chained together to create data processing pipelines:
def numbers():
for i in range(1, 4):
yield i
def squared(seq):
for num in seq:
yield num ** 2
pipeline = squared(numbers())
print(list(pipeline)) # Output: [1, 4, 9]
Generators are a fundamental concept in Python, offering a blend of efficiency and elegance. They're particularly useful in data processing, file I/O, and when working with large datasets. By mastering generators, you'll be able to write more efficient and scalable Python code.