The Python generator is useful, but once you use it in a loop in a for statement, and then try to use it in a for statement again, it looks like a carappo.
def i(n):
yield n + 1
yield n + 2
g = i(10)
print('first time:')
for n in g:
print(n)
print('second time:')
for n in g:
print(n)
The output is
first time:
11
12
second time:
It will be. No elements are iterated in the second for
loop.
In situations where you want 11
and 12
to come back in the second and subsequent for
loops, the following techniques worked.
class ReiteratableWrapper(object):
def __init__(self, f):
self._f = f
def __iter__(self):
return self._f()
def i(n):
yield n + 1
yield n + 2
import functools
f = functools.partial(i, 10)
g2 = ReiteratableWrapper(f)
for n in g2:
print(n)
for n in g2:
print(n)
The ReiteratableWrapper
class takes one generator function. Since it is called without giving an argument internally, if you want to make a generator call with an argument, create a function without arguments by using the functools.partial
function etc. as in the example.
The expression evaluated in the context after the in of the for statement is called the __iter__
method.
Therefore, an instance of ReiteratableWrapper
will automatically create a new generator every time.
However, each time the __iter__
method is evaluated, the generator function is evaluated and executed, so if there are side effects in the generator function call such as the number of times the generator function can be executed is limited, it cannot be used over and over again. I think there is something.
I think the technique introduced this time is effective for content that can be repeated, such as reading from a file in order to save memory, issuing a query to the DB each time and iterating in order.
Recommended Posts