Python for循环跳过其他循环? [英] Python for loop skipping every other loop?

查看:908
本文介绍了Python for循环跳过其他循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个奇怪的问题。有人看到我的代码有什么问题吗?

 对于x的问题:
forms.append((SectionForm .pOST,prefix = str(x.id)),x))
打印附加+ str(x)
表单中的(表单,问题)
打印测试 + str(question)
如果form.is_valid():
forms.remove((form,question))
打印已删除+ str(问题)
a = form。 save(commit = False)
a.audit = audit
a.save()
else:
flag_error = True
pre>

结果:

 附加问题50 
附加问题51
附加问题52
测试问题50
已删除问题50
测试问题52
已删除的问题52
/ pre>

似乎跳过了问题51.它被附加到列表中,但是for循环会跳过它。任何想法?

解决方案

您正在修改对象的内容表单当你说:

  forms.remove((form,question))

根据 c $ c>语句的的Python文档,这不安全(重点是我的):


Python中的for语句与C或Pascal中可能使用的语句有所不同。而不是总是迭代数字的算术进程(如Pascal),或者给予用户定义迭代步骤和停止条件(如C)的能力,Python的for语句迭代任何序列的项目(列表或一个字符串),按顺序出现在序列中。



修改循环中迭代的序列是不安全的 (这仅适用于可变序列类型,例如列表)。如果您需要修改您正在迭代的列表(例如,要复制所选项目),则必须遍历一个副本。切片符号使得这样非常方便:

 在[:]中的x:#制作整个列表的切片副本
...如果len(x)> 6:a.insert(0,x)


另请参见来自 Python语言参考的段落,其中说明了正在发生的事情:


当循环修改序列时,这是一个微妙的(这只能发生在可变序列,即列表)。内部计数器用于跟踪接下来使用哪个项目,并且每次迭代都会增加该计数器。当该计数器达到序列的长度时,循环终止。 这意味着如果套件从序列中删除当前(或前一个)项目,则将跳过下一个项目(因为它获取了已经被处理的当前项目的索引)。同样如果套件在当前项目之前的序列中插入一个项目,则下一次通过循环将再次处理当前项目。


有很多解决方案。您可以按照他们的建议并创建副本。另一种可能性是由于循环的第二个创建一个新的列表,而不是直接修改表单。选择取决于您...


I have a weird problem. Does anyone see anything wrong with my code?

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

Results in:

Appended Question 50
Appended Question 51
Appended Question 52
Testing Question 50
Deleted Question 50
Testing Question 52
Deleted Question 52

It seems to skip question 51. It gets appended to the list, but the for loop skips it. Any ideas?

解决方案

You are modifying the contents of the object forms that you are iterating over, when you say:

forms.remove((form,question))

According to the Python documentation of the for statement, this is not safe (the emphasis is mine):

The for statement in Python differs a bit from what you may be used to in C or Pascal. Rather than always iterating over an arithmetic progression of numbers (like in Pascal), or giving the user the ability to define both the iteration step and halting condition (as C), Python’s for statement iterates over the items of any sequence (a list or a string), in the order that they appear in the sequence.

It is not safe to modify the sequence being iterated over in the loop (this can only happen for mutable sequence types, such as lists). If you need to modify the list you are iterating over (for example, to duplicate selected items) you must iterate over a copy. The slice notation makes this particularly convenient:

for x in a[:]: # make a slice copy of the entire list
...    if len(x) > 6: a.insert(0, x)

See also this paragraph from the Python Language Reference which explains exactly what is going on:

There is a subtlety when the sequence is being modified by the loop (this can only occur for mutable sequences, i.e. lists). An internal counter is used to keep track of which item is used next, and this is incremented on each iteration. When this counter has reached the length of the sequence the loop terminates. This means that if the suite deletes the current (or a previous) item from the sequence, the next item will be skipped (since it gets the index of the current item which has already been treated). Likewise, if the suite inserts an item in the sequence before the current item, the current item will be treated again the next time through the loop.

There are a lot of solutions. You can follow their advice and create a copy. Another possibility is to create a new list as a result of your second for loop, instead of modifying forms directly. The choice is up to you...

这篇关于Python for循环跳过其他循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆