Reputation: 31
I have an infinite generator object which yields some numbers, like below:
def index_generator():
i = 0
while True:
yield i**2
i += 1
my_gen = index_generator()
for i in range(100):
print(next(my_gen)) # outputs 0,1,4,9, ...
Now I need to reset variable i
to zero after some iterations, to use the generator again; let's say 100 more times in my code. I can't repeat my_gen = index_generator()
every time. So, any solutions?
Upvotes: 3
Views: 428
Reputation: 27609
A way with send
which allows to (re)set i
to a desired value:
def index_generator():
i = 0
while True:
reset = yield i**2
if reset is None:
i += 1
else:
i = reset - 1
Demo usage:
my_gen = index_generator()
print([next(my_gen) for _ in range(5)])
my_gen.send(0)
print([next(my_gen) for _ in range(5)])
my_gen.send(100)
print([next(my_gen) for _ in range(5)])
Output:
[0, 1, 4, 9, 16]
[0, 1, 4, 9, 16]
[10000, 10201, 10404, 10609, 10816]
A variation that doesn't use the - 1
trick but instead just yields:
def index_generator():
i = 0
while True:
reset = yield i**2
if reset is None:
i += 1
else:
i = reset
yield
Upvotes: 2
Reputation: 51063
One option is to write a class with a __next__
method, so it can be used as an iterator, and a reset
method which resets i
. The __iter__
method returning self
is also needed if you aren't just calling next
manually.
class IndexGenerator:
def __init__(self):
self.i = 0
def __next__(self):
r = self.i ** 2
self.i += 1
return r
def reset(self):
self.i = 0
def __iter__(self):
return self
Usage example:
>>> g = IndexGenerator()
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> g.reset()
>>> next(g)
0
>>> next(g)
1
>>> for x in g:
... print(x)
... if x > 10: break
...
4
9
16
Upvotes: 6
Reputation: 158
Can you do something like this instead?
for i, val in enumerate(index_generator()):
print(val)
if i > 1000:
break
for each time you need to use it?
The for loop calls the next method implicitly, so this is a bit shorter, and the generator 'resets' each time.
Upvotes: 1