Python - Generators & the yield Keyword in Python
Generators are a special type of function in Python that allow you to produce a sequence of values one at a time, instead of computing and storing all values at once in memory.
1. What is a Generator?
A generator is a function that:
-
Uses the
yieldkeyword instead ofreturn -
Produces values lazily (on demand)
-
Maintains its state between iterations
Unlike a normal function, which runs completely and returns a single result, a generator pauses execution each time it yields a value and resumes from where it left off.
2. Basic Example
def count_up_to(n):
i = 1
while i <= n:
yield i
i += 1
Usage:
for num in count_up_to(5):
print(num)
Output:
1
2
3
4
5
Explanation:
-
The function does not return all values at once
-
Each call to
yieldsends back a value and pauses the function -
When the loop asks for the next value, execution resumes from the last point
3. How yield Works Internally
When a generator function is called:
-
It does not execute immediately
-
It returns a generator object
Example:
gen = count_up_to(3)
print(gen)
Output:
<generator object count_up_to at ...>
To get values, you use:
-
next()function -
Or iterate using a loop
Example:
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3
After all values are exhausted, calling next() raises StopIteration.
4. Difference Between return and yield
| Feature | return | yield |
|---|---|---|
| Output | Single value | Multiple values (sequence) |
| Execution | Ends function | Pauses function |
| Memory | Stores full result | Generates on demand |
5. Why Generators are Important
Memory Efficiency
Consider this:
def get_numbers():
return [i for i in range(1000000)]
This creates a full list in memory.
Now using a generator:
def get_numbers():
for i in range(1000000):
yield i
This:
-
Does not store all numbers
-
Produces one number at a time
-
Saves significant memory
6. Generator Expressions
Similar to list comprehensions, but use parentheses instead of brackets.
List comprehension:
nums = [i*i for i in range(5)]
Generator expression:
nums = (i*i for i in range(5))
Difference:
-
List stores all values
-
Generator computes values when needed
7. Real-World Use Cases
Reading Large Files
def read_file(file):
for line in file:
yield line
This allows processing file line by line instead of loading entire file.
Infinite Sequences
def infinite_counter():
i = 0
while True:
yield i
i += 1
This can run indefinitely without consuming large memory.
Data Pipelines
Generators can be chained together:
def square(nums):
for n in nums:
yield n * n
def even(nums):
for n in nums:
if n % 2 == 0:
yield n
8. Advantages of Generators
-
Memory efficient
-
Faster for large data processing
-
Cleaner and more readable for pipelines
-
Useful for streaming data
9. Limitations
-
Cannot access elements by index
-
Can only be iterated once
-
Debugging can be slightly harder
10. Key Takeaway
Generators allow you to handle large or complex data efficiently by:
-
Producing values only when needed
-
Avoiding unnecessary memory usage
-
Enabling lazy evaluation