When the Python interpreter encounters the
yield
statement, the function's local
variables and execution state are saved and control is returned to the caller.
Jumping between function and caller
The following example tries to demonstrate how it is possible to «jump» between a calling context and a function.
def func(init_val):
local_var = init_val
print(f'yielding {local_var}')
yield local_var
local_var += 5
print(f'yielding {local_var}')
yield local_var
local_var *= 2
print(f'yielding {local_var}')
yield local_var
print('the end.')
gen = func(17)
try:
# gen.__iter__()
print(f'__next()__ returned: {gen.__next__()}')
print(f'__next()__ returned: {gen.__next__()}')
print(f'__next()__ returned: {gen.__next__()}')
print(f'__next()__ returned: {gen.__next__()}')
except StopIteration:
print('Caught StopIteration')
print('--------------------------------------')
gen = func(5)
itr = iter(gen)
try:
print(f'next(itr) = {next(itr)}')
print(f'next(itr) = {next(itr)}')
print(f'next(itr) = {next(itr)}')
print(f'next(itr) = {next(itr)}')
except StopIteration:
print('Caught StopIteration')
When executed, the example prints
yielding 17
__next()__ returned: 17
yielding 22
__next()__ returned: 22
yielding 44
__next()__ returned: 44
the end.
Caught StopIteration
--------------------------------------
yielding 5
next(itr) = 5
yielding 10
next(itr) = 10
yielding 20
next(itr) = 20
the end.
Caught StopIteration
Return type of a def with a yield statement
A function that is defined with
def
and that contains a
yield
statement returns a
generator.
The following simple example defines two functions, one of which has a yield
statement and the other doesn't.
The
type
of both functions is
function
. However, the type of returned
object of the function without
yield
is
int
(the type of
42
) while the the type of the returned object of the function with a
yield
is
generator.
#!/usr/bin/python3
def FuncWithoutYield():
return 42
def FuncWithYield():
yield 42
print(type(FuncWithoutYield))
# <class 'function'>
print(type(FuncWithYield))
# <class 'function'>
retFuncWithoutYield = FuncWithoutYield()
retFuncWithYield = FuncWithYield()
print(type(retFuncWithoutYield))
# <class 'int'>
print(type(retFuncWithYield))
# <class 'generator'>