我可以记住Python生成器吗? [英] Can I memoize a Python generator?
问题描述
我有一个名为 runquery
的函数,该函数调用数据库,然后逐行产生行.我写了一个备忘录装饰器(或更准确地说,我只是从这个stackoverflow问题中偷了一个)在随后的调用中,它只会产生一个空序列,大概是因为生成器的值只能产生一次.
I have a function called runquery
that makes calls to a database and then yields the rows, one by one. I wrote a memoize decorator (or more accurately, I just stole one from this stackoverflow question) but on subsequent calls it just yields an empty sequence, presumably because a generator's values can only be yielded once.
如何修改适用于Python生成器的备忘录装饰器?我意识到我有时需要将其存储在内存中,但我想在装饰器中处理它,而不修改原始函数.
How could I modify the memoization decorator that works for Python generators? I realise I will need to store it in memory at some point but I'd like to handle this within the decorator and not modify the original function.
记忆功能的当前代码为:
The current code of the memoization function is:
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
推荐答案
我意识到这有点老了,但是对于那些想要完整解决方案的人:这是一个基于jsbueno的建议的解决方案:
I realise this is somewhat of an old question, but for those who want a full solution: here's one, based on jsbueno's suggestion:
from itertools import tee
from types import GeneratorType
Tee = tee([], 1)[0].__class__
def memoized(f):
cache={}
def ret(*args):
if args not in cache:
cache[args]=f(*args)
if isinstance(cache[args], (GeneratorType, Tee)):
# the original can't be used any more,
# so we need to change the cache as well
cache[args], r = tee(cache[args])
return r
return cache[args]
return ret
这篇关于我可以记住Python生成器吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!