我正在尝试编写一个函数来基于列表构建扁平化的生成器树。所以如果我有一个项目列表,我想从一个空生成器开始,对第一个项目和空生成器调用一个函数,对第二个项目和第一个函数调用的输出调用函数,然后调用第三项上的函数和第二个函数调用的输出,依此类推。 重要的是,在最终生成器上调用 next
之前,我不想实际评估任何东西!
所以,如果我们在列表和生成器上调用的函数被称为 foo
,(显然它也输出一个生成器),并且项目列表是 list
...
现在,我拥有的是一个看起来像这样的原型(prototype):
>>> tree = iter([{}])
>>> tree = chain.from_iterable((foo(list[0], p) for p in tree))
>>> tree = chain.from_iterable((foo(list[1], p) for p in tree))
>>> tree = chain.from_iterable((foo(list[2], p) for p in tree))
>>> list(tree)
这确实有效。它会正确评估所有内容,最重要的是不会进行任何不必要的评估(以整数开头的行是打印出来的日志,当某些事情实际上是:
>>> next(tree)
Called on 0
Called on 1
Called on 2
Result A
>>> next(tree)
Called on 1
Called on 2
Result B
不幸的是,当我尝试使用循环让它在任意长度的 tail
上工作时:
tree = iter([{}])
for item in list:
tree = chain.from_iterable((foo(item, p) for p in tree))
这是行不通的。相反,tree
变量被设置为 foo
调用的结果 empty 可能性,就好像它是唯一被评估的东西一样!我不知道发生了什么,尽管我预感是因为有指针或其他东西。
如有任何帮助,我们将不胜感激!
这里对递归的调用很清楚:
import itertools as it
def lazy_reduce(list_, tree_base, i=None):
if i is None:
i = len(list_)
if i < 0:
return iter(tree_base)
return it.chain.from_iterable(
foo(list_[i], p)
for p in lazy_reduce(list_, tree_base, i - 1)
)
我是一名优秀的程序员,十分优秀!