最近,我在阅读Python的“函数式编程指南”时,发现了一个名为test_generators.py
的标准模块,在其中找到了以下生成器:
# conjoin is a simple backtracking generator, named in honor of Icon's
# "conjunction" control structure. Pass a list of no-argument functions
# that return iterable objects. Easiest to explain by example: assume the
# function list [x, y, z] is passed. Then conjoin acts like:
#
# def g():
# values = [None] * 3
# for values[0] in x():
# for values[1] in y():
# for values[2] in z():
# yield values
#
# So some 3-lists of values *may* be generated, each time we successfully
# get into the innermost loop. If an iterator fails (is exhausted) before
# then, it "backtracks" to get the next value from the nearest enclosing
# iterator (the one "to the left"), and starts all over again at the next
# slot (pumps a fresh iterator). Of course this is most useful when the
# iterators have side-effects, so that which values *can* be generated at
# each slot depend on the values iterated at previous slots.
def simple_conjoin(gs):
values = [None] * len(gs)
def gen(i):
if i >= len(gs):
yield values
else:
for values[i] in gs[i]():
for x in gen(i+1):
yield x
for x in gen(0):
yield x
我花了一些时间才理解它的工作原理。它使用可变列表
values
来存储迭代器产生的结果,并且第N+1个迭代器返回values
,这个值通过整个迭代器链传递。当我在阅读有关函数式编程的内容时,我偶然发现了这段代码,开始思考是否可以使用函数式编程(使用
itertools
模块中的函数)重写这个conjoin生成器。有很多以函数式风格编写的例程(只需看一下“Recipes”部分的结尾即可)。但不幸的是,我没有找到任何解决方案。
那么,是否可能仅使用
itertools
模块就用函数式编程编写这个conjoin生成器呢?谢谢
map
或zip
。它更接近笛卡尔积,但混入了函数应用的变化。 - recursiveitertools.product
。如果你想要副作用,那么你就必须自己动手实现。两者不能兼得。 - Katriel