general summary
Generators in Python offer a more memory-efficient way to iterate through sequences, notably for large ones.
They are defined with functions containing at least one yield statement and return an iterator object. This means they are \textbf{lazy-evaluating and one-time-use}, generating elements on-demand.
Key Benefits
Memory Efficiency: Generators only keep track of the current state rather than the entire sequence, an advantage over lists.
Speed: For processes needing partial results (e.g., factorials), generators are faster and provide immediate output.
Simplicity: They simplify the process of creating iterators, eliminating the need for constructing custom classes.
Code Example: Generators
# Simple Iterator vs Generator
Iterator - Uses List
def basic_iterator(n):
my_list = list(range(n))
for item in my_list:
yield item
Generator Function
def generator_function(n):
for item in range(n):
yield item
Generator Expression
my_generator = (i for i in range(10) if i % 2 == 0)List Comprehensions and Generators
Both list comprehensions and generator expressions create sequences based on existing ones, but the former builds a list, while the latter constructs a generator.
List Comprehension: Enclosed within square brackets, e.g., [i ** 2 for i in range(5)].
Generator Expression: Enclosed within parentheses, e.g., (i ** 2 for i in range(5)).
When to Use Generators and Lists
Use Lists when the sequence is small, and multiple iterations or random access are necessary.
Use Generators when the dataset is large, and memory efficiency is crucial.