Вы изменяете содержимое объекта forms
, который вы повторяете, когда говорите:
forms.remove((form,question))
Согласно документации Python оператора for
, это небезопасно (ударение мое):
Оператор for в Python немного отличается от того, к чему вы привыкли в C или Pascal. Вместо того, чтобы всегда выполнять итерацию по арифметической последовательности чисел (как в Pascal) или давать пользователю возможность определять как шаг итерации, так и условие остановки (как C), оператор Python for выполняет итерации по элементам любой последовательности (список или строка), в том порядке, в котором они появляются в последовательности.
Не безопасно изменять итерируемую последовательность в цикле (это может происходить только для изменяемых типов последовательностей, таких как списки). Если вам нужно изменить список, который вы перебираете (например, для дублирования выбранных элементов), вы должны перебрать копию. Обозначение среза делает это особенно удобным:
for x in a[:]: # make a slice copy of the entire list
... if len(x) > 6: a.insert(0, x)
См. Также этот абзац из Python Language Reference , который точно объясняет, что происходит:
Существует тонкость, когда последовательность модифицируется циклом (это может происходить только для изменяемых последовательностей, то есть списков). Внутренний счетчик используется для отслеживания того, какой элемент используется следующим, и он увеличивается на каждой итерации. Когда этот счетчик достигнет длины последовательности, цикл завершается. Это означает, что если набор удаляет текущий (или предыдущий) элемент из последовательности, следующий элемент будет пропущен (так как он получает индекс текущего элемента, который уже был обработан). Аналогично, если набор вставляет элемент в последовательность перед текущим элементом, текущий элемент будет обработан снова в следующий раз в цикле.
Есть много решений. Вы можете последовать их совету и создать копию. Другая возможность - создать новый список в результате вашего второго цикла for
вместо непосредственного изменения forms
. Выбор за вами ...