Memoizing Generators

Michael Sparks zathras at thwackety.com
Tue Jul 8 20:39:31 EDT 2003


> Now, the two remaining issues are 1) can we "unify" the generator
> memoization with the "standard" memoization and 2) can we deal with lists
> as well (i.e. my generator was returning tuples ... since I'm scared of
> lists in recursive generator contexts *wink*).  
> One other memoization issues:  what if the args (which will become
> keys) are mutables ... in particular, lists.  I suppose we could just
>  tuple() them up?

How would you deal with the following generator? (On the assumption you want a 
a general purpose memoisation mechanism :)

def retrieveData(source=None, command=True,blocksize=1024):
   if source:
      if not command:
         fh = open(source, "rb",0)
     else:
         fh = os.popen(self.command)
   else:
      fh = sys.stdin
   try:
      try:
         while 1:
            data = fh.read(blocksize)
            if data:
               yield data
            else:
               raise Finality
      except Exception, e:
         if source:
            fh.close()
         raise e
   except Finality:
      pass

If your source is a network connection, or a real user this becomes further 
indeterminate... Not a suggestion to not try, just worth considering :)

The other problem as I see it with your implementation is it expects the 
generator to terminate. This is far from guaranteed - generators are useful 
for dealing with infinite sequences/lists and working with functions that 
might not halt. (eg calculate the best approximation of pi that you can based 
on time available, not based on number of iterations/memory available)

eg
def runGenerator(fn,args,timeAlloted):
   tstart = time.time()
   gen = fn(args).next
   r = gen()
   while 1:
      if time.time()-tstart >=timeAlloted:
         break
      r = gen()
   return r

Consider the possibility that the function is a "next move" in chess and the 
time is set by the first player to "hard" - ie lots of time. The next time a 
player comes along with the time set to "easy", the memoised version won't be 
aware of this in this scenario and returns the hard result (but very 
quickly...), or worse hits stop iteration - which the original version 
wouldn't. Or even worse - occasionally hits the StopIteration and normally 
returns the "hard" result aroung 80-90% of the time.

That said memoising _good_ chess results from certain positions _might_ be 
considered a good thing. It's still an issue though.

Regards,


Michael.






More information about the Python-list mailing list