Генераторы
(функции с yield
вместо return
) действительно могут рассматриваться как "ленивые" (и itertools.chain
может связывать их так же, как и любой другой итератор, если вы это подразумеваете под "цепью").
Но если под «цепочкой» (и ленивым) вы подразумеваете, что хотите позвонить fee().fie().fo().fum()
, и вся «тяжелая работа» происходит только в fum
(что похоже на то, что делает SQLAlchemy)тогда генераторы не помогут - вам нужен шаблон проектирования «Обещание», где каждая функция / метод (кроме той, которая фактически выполняет всю работу) возвращает объект, который записывает все условия, параметры и ограниченияна операции, и одна трудолюбивая функция использует эту информацию, чтобы наконец выполнить работу.
Чтобы привести очень простой пример, скажем, что «тяжелая работа» выполняет вызов RPC вида 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
).