python – 停止递归生成器和排列

作为练习,我一直在尝试各种方法来生成Python中列表的所有排列 – 递归,非递归…… – 并将性能与itertools.permutations()进行比较.但是我遇到了递归方法的生成器版本的问题,它没有使用StopIteration异常干净地完成,而是抛出了一个IndexError:

def spawnperms(alist):
    """same algorithm as recursive option, but a generator"""
    if (alist == []):
        yield []
    for perm in spawnperms(alist[:-1]):
        for i in range(len(perm)+1):
            yield perm[:i] + [alist[-1]] + perm[i:]

从Python解释器调用它:

>>> for i in spawnperms(range(3)):
...     print i
... 
[2, 1, 0]
[1, 2, 0]
[1, 0, 2]
[2, 0, 1]
[0, 2, 1]
[0, 1, 2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in spawnperms
  File "<stdin>", line 5, in spawnperms
  File "<stdin>", line 5, in spawnperms
  File "<stdin>", line 7, in spawnperms
IndexError: list index out of range

哎哟.我尝试使用pdb逐步完成它,这几乎在我的大脑中创建了一个堆栈溢出,但我所理解的是递归“向下”到空列表,然后外部(我认为)for循环用完了索引.

我该如何更正我的代码?

编辑:从Mark Byers的一个看似简单的正确答案中学到的一点是,清晰的编码实践可以防止错误.如果不管我是否认为可以重新审视这种情况,我是否会系统地使用其他方法,这不会发生.它仍然感觉非常愚蠢!

解决方法:

你错过了其他的:

if (alist == []):
    yield []
else:
    for ...

这是因为收益率的表现方式与收益率不同.当您请求下一个值时,在yield语句之后继续执行.

上一篇:PHP从2D数组计算每个排列


下一篇:php – “展开”一个字符串