为什么删除else导致递归函数重复结果?

时间:2018-05-16 07:49:52

标签: python if-statement recursion

当我使用以下语句在Python控制台上执行以下代码时,

for L in permute([12, 32, 3]):
    print(L)

代码如下,

def permute(L):
    if len(L) <= 1:
        yield L
    else:
        for i in range(0, len(L)):
            L[0], L[i] = L[i], L[0]
            for L1 in permute(L[1:]):
                yield [L[0]] + L1

每个结果只出现一次。但是,如果我删除else并删除其下方代码的相关缩进,我会收到两次结果。 为什么会这样?

2 个答案:

答案 0 :(得分:1)

来自docs

  

yieldreturn语句之间的最大区别在于,在达到yield时,生成器的执行状态将被暂停,并保留局部变量。在下次调用生成器的__next__()方法时,该函数将继续执行。

所以发生这种情况是因为if正文不会中断执行,因此它会向前移动到下一个yield语句,并且else子句到达函数结尾并隐式返回。

检查

def counter(step):
    assert step >= 0, ('Can count only from non-negative number, but found '
                       + str(step))
    if step == 0:
        print('Reached end')
        yield step
    print('Step', step)
    for sub_step in counter(step - 1):
        yield sub_step

>>> list(counter(1))

Step 1
Reached end
Traceback (most recent call last):
  File "<input>", line 13, in <module>
Step 0
  File "<input>", line 8, in counter
  File "<input>", line 8, in counter
  File "<input>", line 3, in counter
AssertionError: Can count only from non-negative number, but found -1

def counter(step):
    assert step >= 0, ('Can count only from non-negative number, but found '
                       + str(step))
    if step == 0:
        print('Reached end')
        yield step
    else:
        print('Step', step)
        for sub_step in counter(step - 1):
            yield sub_step
    # implicitly returns here

>>> list(counter(1))
Step 1
Reached end

我们可以看到,如果没有else执行,我们会继续执行counterstep等于-1

因此,您可以离开else或重构您的if子句并在其中添加return语句以明确完成执行,如

def permute(L):
    if len(L) <= 1:
        yield L
        return
    for i in range(0, len(L)):
        L[0], L[i] = L[i], L[0]
        for L1 in permute(L[1:]):
            yield [L[0]] + L1

进一步阅读

答案 1 :(得分:0)

因为你yield两次,如果没有else循环。