gpt4 book ai didi

python - 以函数式风格制作的 Conjoin 函数

转载 作者:太空狗 更新时间:2023-10-30 01:10:06 24 4
gpt4 key购买 nike

最近在看Python "Functional Programming HOWTO" ,我遇到了那里提到的 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 module 中的函数)重写这个连词生成器。有很多以函数式风格编写的例程(只需看一下食谱部分的 this 文章的末尾)。

但是,不幸的是,我还没有找到任何解决方案。

那么,是否可以仅使用 itertools module 使用函数式编程来编写这个连词生成器? ?

谢谢

最佳答案

这似乎有效,而且它仍然很懒惰:

def conjoin(gs):
return [()] if not gs else (
(val,) + suffix for val in gs[0]() for suffix in conjoin(gs[1:])
)

def range3():
return range(3)

print list(conjoin([range3, range3]))

输出:

[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

显示可变状态的示例用法:

x = ""
def mutablerange():
global x
x += "x"
return [x + str(i) for i in range(3)]

print list(conjoin([range3, mutablerange]))

输出:(观察'x'的数量增加)

[(0, 'x0'), (0, 'x1'), (0, 'x2'), (1, 'xx0'), (1, 'xx1'), (1, 'xx2'), (2, 'xxx0'), (2, 'xxx1'), (2, 'xxx2')]

如果我们使用 itertools.product:

x = ""
print list(itertools.product(range3(), mutablerange()))

结果如下:

[(0, 'x0'), (0, 'x1'), (0, 'x2'), (1, 'x0'), (1, 'x1'), (1, 'x2'), (2, 'x0'), (2, 'x1'), (2, 'x2')]

因此,可以清楚地看到,itertools.product 缓存了迭代器返回的值。

关于python - 以函数式风格制作的 Conjoin 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7093121/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com