我可以记住Python生成器吗? [英] Can I memoize a Python generator?

查看:61
本文介绍了我可以记住Python生成器吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆