Generators
What are Generators?
Imagine you have a magic box that gives you one candy at a time whenever you ask for it, instead of giving you all the candies at once. This way, you don’t have to carry all the candies with you and can enjoy them one by one. In Python, this magic box is called a generator.
Generators are special functions that allow you to create an iterator. An iterator is something you can loop through (like a list), but instead of generating all the items at once, it generates them one at a time.
Why Use Generators?
- Memory Efficiency: Generators are great because they generate items one at a time and only when you need them. This is super useful when you’re dealing with large data sets.
- Simpler Code: They make your code cleaner and more readable, especially when working with large or infinite sequences.
How Do Generators Work?
Generators use the yield
keyword. When the generator function is called, it doesn’t execute the code. Instead, it returns a generator object. When you start iterating over this object, the function starts executing until it hits yield
. Then, it “pauses” and returns the value. When you continue iterating, it picks up right after the yield
.
Example Time!
Let’s look at a simple example:
def magic_box():
yield "Candy 1"
yield "Candy 2"
yield "Candy 3"
# Creating the generator object
my_candy_generator = magic_box()
# Getting the candies one by one
print(next(my_candy_generator)) # Output: Candy 1
print(next(my_candy_generator)) # Output: Candy 2
print(next(my_candy_generator)) # Output: Candy 3
In this example, magic_box
is a generator function. Each time we call next(my_candy_generator)
, we get the next candy.
Using Generators in Loops
Generators can be used in loops too! This is where they really shine.
def count_up_to(max):
count = 1
while count <= max:
yield count
count += 1
# Using the generator in a loop
for number in count_up_to(5):
print(number)
Output:
1
2
3
4
5
Here, count_up_to
generates numbers from 1 to the maximum number you give it. Notice how clean and simple the code is!
Practice Questions
- Write a generator function called
even_numbers
that yields even numbers starting from 0 up to a given maximum.
def even_numbers(max):
number = 0
while number <= max:
yield number
number += 2
# Test the generator
for even in even_numbers(10):
print(even)
Output:
0
2
4
6
8
10
- Create a generator function called
fibonacci
that yields the Fibonacci sequence up to a given number of terms.
def fibonacci(n):
a, b = 0, 1
count = 0
while count < n:
yield a
a, b = b, a + b
count += 1
# Test the generator
for fib in fibonacci(5):
print(fib)
Output:
0
1
1
2
3
Solutions to Practice Questions
- even_numbers
def even_numbers(max):
number = 0
while number <= max:
yield number
number += 2
# Test the generator
for even in even_numbers(10):
print(even)
- fibonacci
def fibonacci(n):
a, b = 0, 1
count = 0
while count < n:
yield a
a, b = b, a + b
count += 1
# Test the generator
for fib in fibonacci(5):
print(fib)
Summary
- Generators are like magic boxes that give you items one at a time.
- They use the
yield
keyword to “pause” and “resume” the function. - Generators are memory efficient and make your code simpler.
- You can loop through generators just like you do with lists, but they generate items on-the-fly.
Generators are super handy tools in Python. With them, you can handle large amounts of data efficiently and write cleaner code. Keep practicing, and you’ll become a generator wizard in no time!