Ho una funzione chiamata runquery
che effettua chiamate a un database e quindi restituisce le righe, una alla volta. Ho scritto un decoratore memoize (o più esattamente, ne ho appena rubato uno da this stackoverflow question) ma nelle chiamate successive si ottiene solo una sequenza vuota, presumibilmente perché i valori di un generatore possono essere restituiti solo una volta.Posso memoizzare un generatore Python?
Come è possibile modificare il decoratore di memoizzazione che funziona con i generatori Python? Mi rendo conto che a un certo punto dovrò memorizzarlo in memoria, ma mi piacerebbe gestirlo nel decoratore e non modificare la funzione originale.
Il codice attuale della funzione Memoizzazione è:
def memoized(f):
# Warning: Doesn't work if f yields values
cache={}
def ret(*args):
if args in cache:
return cache[args]
else:
answer=f(*args)
cache[args]=answer
return answer
return ret
Grazie per la tua illustrazione! Ho impiegato anni per capire come usare 'tee'. __But__ Penso che ci sia un problema durante il controllo dell'istanza: dovresti provare contro 'collections.Iterable', dato che il test contro' types.GeneratorType' funziona solo una volta: quando si restituisce l'iteratore memorizzato nella cache (oggetto 'iterator.tee') al terzo chiamata alla funzione, la cache restituirà un iteratore esaurito. –
Hai ragione! Tuttavia, anche il test contro 'collections.Iterable' sarebbe sbagliato, dal momento che liste e stringhe ecc. Sono anch'esse iterabili. Ho cambiato i set in '(GeneratorType, _tee)', quindi funziona anche per gli oggetti tee. – Robin
Sì, è sicuramente un po 'eccessivo, ma, in Python 2.7, non c'è alcun oggetto '_tee' in' itertools', e la funzione 'itertools.tee' restituisce oggetti' itertools.tee'. Ovviamente, questa non è la loro classe, quindi il test contro 'itertools.tee' non ha senso (e inoltre non funziona), quindi la mia proposta con' collections.Iterable'. Sotto quale versione di Python hai testato il tuo codice? –