Python for循环跳过其他循环?
我有一个奇怪的问题。有没有人看到我的代码有什么问题?Python for循环跳过其他循环?
for x in questions:
forms.append((SectionForm(request.POST, prefix=str(x.id)),x))
print "Appended " + str(x)
for (form, question) in forms:
print "Testing " + str(question)
if form.is_valid():
forms.remove((form,question))
print "Deleted " + str(question)
a = form.save(commit=False)
a.audit = audit
a.save()
else:
flag_error = True
结果:
Appended Question 50
Appended Question 51
Appended Question 52
Testing Question 50
Deleted Question 50
Testing Question 52
Deleted Question 52
这似乎跳过问题51.被添加到列表中,但for循环跳过它。有任何想法吗?
要修改的对象forms
的,你是迭代的内容,当你说:
forms.remove((form,question))
按照Python documentation of the for
statement,这不是安全(重点是我的):
Python中的for语句与C或Pascal中的for语句有所不同。 Python的for语句并不总是迭代数字的算术级数(比如在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
。选择取决于你...
您正在从forms
中删除对象,同时迭代它。这应该会导致你看到的行为(http://docs.python.org/reference/compound_stmts.html#the-for-statement)。
解决方法是迭代该列表的副本,或将要删除的表单添加到单独的集合,然后执行删除操作。
使用窗体上的remove方法(我认为是一个列表)更改列表的大小。所以想想这样
[ 50, 51, 52 ]
是您的初始列表,并且您要求第一个项目。然后,从列表中删除该项目,所以它看起来像
[51, 52]
但现在你问的第二个项目,所以你得到52
它在哪里说,这是不允许的? – Marcin 2012-03-16 14:50:50
因此,在这种情况下,我会建议标记要删除的问题(或保留要删除的问题的索引列表),并在循环后实际删除它们。 – egor83 2012-03-16 14:52:14
好点,它不安全,但允许。 – 2012-03-16 14:52:35