yield#
yield
is a keyword in Python that is used to return from a function while preserving the state of its local variables, and when such a function is called again, execution continues from the yield
statement where it was interrupted. Any function containing the yield
keyword is called a generator. We can say that yield
is what makes it a generator.
Comparison#
Consider an example where we extract only even numbers from a list. basic_fun
represents the solution without using yield
and yield_fun
represents the solution with the yield
function.
You can use yield
just like return
, but remember - it returns to the function for the next iteration.
def basic_fun(list_of_nums):
return [i for i in list_of_nums if (i%2) == 0]
def yield_fun(list_of_nums):
for i in list_of_nums:
if i % 2 == 0:
yield i
So here both functions have been applied to a list of values. And of course we got the same result:
list_of_nums = [1, 2, 3, 8, 15, 42]
print(
"basic_fun result:",
basic_fun(list_of_nums)
)
print(
"get_even result:",
list(yield_fun(list_of_nums))
)
basic_fun result: [2, 8, 42]
get_even result: [2, 8, 42]
Return value#
Functions that exits with yield
returns generator
- is special object in python.
The following example simply iterates over a list of numbers using the yield
operator and prints each element.
The key idea here is that
During the function call, the function wasn’t actually executed - we don’t have any output from
print
, and we got thegenerator
object as a result;But when we unpacked the
generator
into a list, we got messages and a list as a result.
def experiment_fun(list_of_nums):
for v in list_of_nums:
print(f"processing object: {v}")
yield v
list_of_nums = [10,20,30,40,50]
print("Function execution:")
gen = experiment_fun(list_of_nums)
print("Result:", gen, end = "\n\n")
print("Generator unpacking:")
print("Result:", list(gen))
Function execution:
Result: <generator object experiment_fun at 0x7fada84d4b30>
Generator unpacking:
processing object: 10
processing object: 20
processing object: 30
processing object: 40
processing object: 50
Result: [10, 20, 30, 40, 50]
yield
and return
#
But what happens if you use both yield
and return
in the same function? Nothing special - the function will create generator, but if it has return
in it - it will just stop iterating over generator
.
So the following cell just shows how it might look - it iterates over the passed array while for the first three elements, but then return
is executed so that elements after the third have not been processed.
def experiment_fun(list_of_nums):
for i, v in enumerate(list_of_nums):
print(f"processing object: {v, i}")
yield v
if i > 1:
return "test"
list_of_nums = [10,20,30,40,50]
list(experiment_fun(list_of_nums))
processing object: (10, 0)
processing object: (20, 1)
processing object: (30, 2)
[10, 20, 30]