You modify the contents of the forms object, which you repeat when you say:
forms.remove((form,question))
According to the Python documentation for instructions, this is not safe (emphasis mine):
The for statement in Python is slightly different from what you can use in C or Pascal. Instead of always repeating the arithmetic progression of numbers (for example, in Pascal) or giving the user the ability to determine both the iteration step and the stop condition (like C), the Pythons operator to iterate over elements of any sequence (list or line), in the order they are occurrences in sequence.
It is not possible to change a sequence repeated in a loop (this can only happen for mutable types of sequences, such as lists). If you need to change the list that you are repeating (for example, to duplicate selected items), you must iterate over the copy. Slice notation makes this especially convenient:
for x in a[:]:
See also this paragraph from the Python Reference , which explains exactly what is happening:
There is subtlety when a sequence is modified by a cycle (this can happen only for mutable sequences, i.e. lists). An internal counter is used to track which item is used next, and this increases at each iteration. When this counter reaches the length of the sequence, the loop ends. This means that if a package removes the current (or previous) item from the sequence, the next item will be skipped (since it gets the index of the current item that has already been processed). Similarly, if a package inserts an element in a sequence before the current element, the current element will be processed again the next time through the loop.
There are many solutions. You can follow their advice and create a copy. Another possibility is to create a new list as a result of the second for loop instead of directly changing forms . The choice is up to you ...
source share