如何在Python中编写可链式的惰性函数?
我想写一些既懒惰又可以连着用的函数。有什么好的方法吗?我知道一种方法是用 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
)。