如何在Python中编写可链式的惰性函数?

2 投票
1 回答
1181 浏览
提问于 2025-04-16 00:01

我想写一些既懒惰又可以连着用的函数。有什么好的方法吗?我知道一种方法是用 yield 来代替 return

我希望这些函数的懒惰程度和 sqlalchemy 从数据库获取数据时的懒惰程度类似。

1 个回答

7

生成器(就是用 yield 而不是 return 的函数)确实可以被看作是“懒惰”的(而且 itertools.chain 可以像其他迭代器一样把它们串联起来,如果你说的“可串联”是这个意思的话)。

但是,如果你说的“可串联”(和懒惰)是指你想调用 fee().fie().fo().fum(),并且所有的“繁重工作”只在 fum 中完成(这看起来更像是 SQLAlchemy 的做法),那么生成器就不太管用了——你需要的是“Promise”设计模式。在这个模式中,每个函数/方法(除了那个真正做工作的函数)都会返回一个对象,这个对象记录了所有的条件、参数和操作的限制,而那个辛苦工作的函数则利用这些信息来最终完成工作。

举个很简单的例子,假设“繁重工作”是执行一个形式为 remote(host, **kwargs) 的远程调用。你可以把这个包装成“懒惰可串联”的样子,如下所示:

class RPC(object):
    def __init__(self, host):
        self._host = host
        self._kws = {}
    def doit(self, **morekws):
        return remote(self._host, **dict(self._kws, **morekws))
    def __getattr__(self, name):
        def setkw(value):
            self._kws[name] = value
            return self
        return setkw

现在,RPC(x).foo('bar').baz('bap').doit() 会调用 remote(x, foo=bar, baz=bap)(当然,你可以保存链中的中间状态,把它们作为参数传来传去,等等,直到调用 doit)。

撰写回答