我有以下递归函数来生成(命名)位置列表的有效配置列表,其中每个位置只能使用一次:
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
。
现在,根据输入configurations
,MemoryError
列表会很快变大,导致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
但这根本不会产生任何结果。我做错了什么?
答案 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
。