如何将递归函数转换为生成器?

时间:2015-11-10 02:47:12

标签: python python-2.7 recursion generator

我有以下递归函数来生成(命名)位置列表的有效配置列表,其中每个位置只能使用一次:

named_positions = [('a', [0,1,2]),
                   ('b', [1,3]),
                   ('c', [1,2])]

for comb in generate_configurations([], named_positions, ()):
    print comb

以下是我如何称呼它的示例:

(0, 1, 2)
(0, 3, 1)
(0, 3, 2)
(1, 3, 2)
(2, 3, 1)

其中给出了以下输出:

named_positions = [('a', [3]), ('b', [3])]

此外,可能存在 no 有效组合,例如named_positions

现在,根据输入configurationsMemoryError列表会很快变大,导致def generate_configurations(named_positions, current): if len(current) == len(named_positions): yield current name, positions = named_positions[len(current)] for x in positions: if x not in current: generate_configurations(named_positions, current + (x,)) named_positions = [('a', [0,1,2]), ('b', [1,3]), ('c', [1,2])] for comb in generate_configurations(named_positions, ()): print comb 。我相信这个函数可以重写为生成器,所以我尝试了以下内容:

EXPOSE 8080

但这根本不会产生任何结果。我做错了什么?

2 个答案:

答案 0 :(得分:1)

您需要yield向上递归调用堆栈,否则内部yield永远不会发生并被丢弃。由于这是标记的Python 2.7,递归调用将通过更改:

来处理
if x not in current:
    # Creates the generator, but doesn't run it out to get and yield values
    generate_configurations(named_positions, current + (x,))

为:

if x not in current:
    # Actually runs the generator and yields values up the call stack
    for y in generate_configurations(named_positions, current + (x,)):
        yield y

在Python 3.3及更高版本中,您可以直接委派:

if x not in current:
    yield from generate_configurations(named_positions, current + (x,)):

答案 1 :(得分:1)

当您使用生成器时,您需要确保您的子生成器递归调用返回到调用方法。

def recur_generator(n):
    yield my_thing
    yield my_other_thing
    if n > 0:
        yield from recur_generator(n-1)

请注意,yield from是将yield调用传递回父调用的内容。

您应该将递归调用行更改为

yield from generate_configurations(named_positions, current + (x,))

否则,您的发电机就可以了。

编辑:没有注意到这是python2。你可以使用

for x in recur_generator(n-1):
    yield x

而不是yield from