В качестве упражнения я пробовал различные способы генерации всех перестановок списка в 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
вне индексов.
Как я могу исправить свой код?
РЕДАКТИРОВАТЬ: Из одного обманчиво простого правильного ответа Марка Байерса можно извлечь одно:ошибки .Если бы я систематически использовал else
после if
, независимо от того, думал ли я, что условие когда-либо будет пересмотрено, этого бы не случилось.И это все еще кажется очень глупым!