Chapter 11: Iterators and Generators
Iterators and generators are advanced Python features that allow for efficient looping and data generation. They enable you to handle large datasets and compute values lazily, improving performance and memory usage.
Iterators
An iterator is an object that implements the __iter__()
and __next__()
methods. It represents a sequence of values, returning one value at a time when iterated.
Example of an Iterator:
Key Methods:
Method
Description
__iter__()
Returns the iterator object itself.
__next__()
Returns the next item in the sequence or raises StopIteration
.
Custom Iterators
You can create custom iterators by defining a class that implements the __iter__()
and __next__()
methods.
Example:
Generators
A generator is a special type of iterator created using functions and the yield
keyword. Generators are used to lazily produce values one at a time, as needed.
Creating a Generator:
Key Differences Between Generators and Iterators:
Generators are defined using functions and the
yield
keyword.Generators automatically implement the
__iter__()
and__next__()
methods.
Generator Expressions
Generator expressions are similar to list comprehensions but produce values lazily.
Example:
Advantages of Generators
Memory Efficiency: Generate values on the fly instead of storing them in memory.
Lazy Evaluation: Values are computed only when needed.
Readable Code: Easier to implement compared to custom iterators.
Practical Use Cases
Reading Large Files: Process a file line by line without loading the entire file into memory.
Infinite Sequences: Generate an unbounded sequence of values.
Efficient Data Pipelines: Process data streams incrementally.
Exercises
Exercise 1:
Write a custom iterator that generates the Fibonacci sequence up to a given number n
.
Solution:
Exercise 2:
Write a generator function to yield even numbers up to a given number n
.
Solution:
Exercise 3:
Use a generator expression to create a sequence of cubes for numbers 1 through 5.
Solution:
Best Practices
Use generators for processing large datasets or streams to save memory.
Combine generator expressions with functions like
sum()
andmax()
for concise calculations.Prefer
yield
over returning large lists when possible.Test custom iterators to handle edge cases, such as empty sequences.
In the next chapter, we will explore decorators and context managers, which are powerful tools for enhancing and managing Python functions and resources.
Last updated