Python provides a few special methods to manipulate generators!
.send() method allows us to send a value to a generator using the
yield expression. If you assign
yield to a variable the argument passed to the
.send() method will be assigned to that variable. Calling
.send() will also cause the generator to perform an iteration.
Look at the following example to see the behavior of the
def count_generator(): while True: n = yield print(n) my_generator = count_generator() next(my_generator) # 1st Iteration Output: next(my_generator) # 2nd Iteration Output: None my_generator.send(3) # 3rd Iteration Output: 3 next(my_generator) # 4th Iteration Output: None
In the code example above, the generator definition contains the line
n = yield. This assigns the value in
n which will be
None unless a value is passed using
The last 4 lines in the code are 4 iterations, 3 using
next() and one using the
- The 1st iteration creates no output since the execution stops at
n = yieldwhich is before
- The 2nd iteration assigns
n = yieldexpression.
- The 3rd iteration is caused by
my_generator.send(3). The value
3is passed through
yieldand assigned to
- The last, and 4th, iteration, assigns
.send() method can control the value of the generator when a second variable is introduced. One variable holds the iteration value and the other holds the value passed through
def generator(): count = 0 while True: n = yield count if n is not None: count = n count += 1 my_generator = generator() print(next(my_generator)) # Output: 0 print(next(my_generator)) # Output: 1 print(my_generator.send(3)) # Output: 4 print(next(my_generator)) # Output: 5
In the above example, the generator function defines
count = 0 as the iteration value.
n is used to hold the value provided by
yield. Just like
.send() method returns the value of the recent iteration. In this example, the return values are printed using
The updated line,
n = yield count, has 2 behaviors:
- At the start of each iteration the value provided by
yieldis assigned to
n. This value will be
next()causes an iteration or it will be equal to the value passed using
- At the end of each iteration, the value stored in
countis returned by the generator.
n is not None the value stored in
n can be assigned to the iterator variable,
count. This allows the iterator to only change the value of
count when the
.send() method is called.
You are a teacher with a roster of 50 students. You have created a generator,
get_student_ids(), that outputs each student’s id which you then use for assignment grading.
Things to note about the code in the workspace:
MAX_STUDENTSis set to 50 and is used in the
whileloop condition to cutoff the iteration.
student_idis initialized to
1and is incremented at the bottom of the
- The generator currently uses
student_idat the end of each iteration.
forloop at the bottom of the code iterates through the generator object
student_id_generatorand outputs each id.
Run the code to see all 50 ids printed.
When you are interrupted while grading, you need to pick up where you left off! This requires you to start the id generation at a number higher than
1. One way to solve this problem is to change the generator to support the
- Change the
yieldexpression so the value from
yieldis assigned to
- Just below the
yieldexpression check that
nis not equal to
None. If they are not equal, assign the value of
- Still inside the
student_idfrom incrementing by skipping the rest of the iteration.
When you run the code, you should see no change.
To start the iteration at a different id, you want to send the generator a new value during the first iteration.
for loop and before
- Check if
iis equal to the first id number,
- If so, set
ito the return value of the
- Set the argument for the
.send()method so the output starts at