revive a generator
Chris Angelico
rosuav at gmail.com
Fri Oct 21 04:27:40 EDT 2011
On Fri, Oct 21, 2011 at 7:02 PM, Yingjie Lan <lanyjie at yahoo.com> wrote:
> What if the generator involves a variable from another scope,
> and before re-generating, the variable changed its value.
> Also, the generator could be passed in as an argument,
> so that we don't know its exact expression.
>
There's actually no way to know that the generator's even
deterministic. Try this, for instance:
>>> g=(input("Enter value %d or blank to stop: "%n) for n in range(1,11))
>>> for s in g:
if not s: break
print("Processing input: "+s)
It may not be particularly useful, but it's certainly legal. And this
generator cannot viably be restarted. The only way is to cast it to
list first, but that doesn't work when you have to stop reading
expressions from the generator part way.
What you could perhaps do is wrap the generator in something that
saves its values:
>>> class restartable(object):
def __init__(self,gen):
self.gen=gen
self.yielded=[]
self.iter=iter(self.yielded)
def restart(self):
self.iter=iter(self.yielded)
def __iter__(self):
return self
def __next__(self): # Remove the underscores for Python 2
try:
return self.iter.__next__()
except StopIteration:
pass
ret=self.gen.__next__()
self.yielded.append(ret)
return ret
>>> h=restartable(g)
>>> for i in h:
if not i: break
print("Using: ",i)
>>> h.restart()
>>> for i in h:
if not i: break
print("Using: ",i)
Complicated, but what this does is returns a value from its saved list
if there is one, otherwise returns a value from the original
generator. It can be restarted as many times as necessary, and any
time you read "past the end" of where you've read so far, the original
generator will be called upon.
Actually, this model might be useful for a repeatable random-number
generator. But those are more efficiently restarted by means of
reseeding the PRNG.
ChrisA
More information about the Python-list
mailing list