在Python中,循环条件是否会在执行新的迭代之前重新评估?

7

关于Python,当涉及到for循环时,它是否会在重新迭代前重新评估上限?

假设我有以下情况:

def remove(self,list,element):
     for x in range(0,len(list)):
           if somecondition:
               list.pop(x)
len(list)这个条件在执行for循环的下一次迭代之前是否会重新评估?(例如,Objective-C中会这样做)否则,如果弹出了多个元素,则可能会出现越界错误,例如如果删除了1个元素,则最后一次迭代将尝试访问list[len(list)-1]
我已经试着自己调查了,但每次结果都很混乱。 编辑:我认为我的问题与被标记为重复的问题不同,因为我的问题涉及到继续下一次迭代的循环条件,它很容易添加元素而不是删除元素。
为澄清起见,我的问题是询问for循环条件是否会在下一次迭代之前重新检查所提出的条件。

快速检查表明,如果您在迭代期间添加元素,len(some_list) 不会被重新评估。另一方面,如果您循环遍历列表本身并添加元素(for x in some_list:),则迭代器会变得混乱。在 Python 中通常会避免在迭代过程中修改集合,除非您知道自己在做什么。 - snakecharmerb
你尝试了什么调查 - 这很容易证明。 - Clifford
你应该了解Python中的生成器。for循环只是一个包装器,用于try、iter=next(gen) do loop和catch。这可以提供更深入的理解。 - Veltzer Doron
3个回答

10
关于for语句的文档已经表述得很清楚了:

for语句用于遍历序列(如字符串、元组或列表)或其他可迭代对象:

for_stmt ::= "for" target_list "in" expression_list ":" suite ["else" ":" suite]

表达式列表只会被计算一次,它应该返回一个可迭代对象。对于expression_list的结果会创建一个迭代器。然后按照迭代器返回的顺序,每次为迭代器提供的每个项目执行一次suite代码块。

[我强调]

因此,在您的情况下,range(0,len(list)) 只会被计算一次。

我明白了,如果在循环内修改了Y的值,那么假设range(0,Y)也是如此,我的理解是正确的吗? - Andrew1024
1
无论您是什么表达式,都会如此。range对象只创建一次,然后进行迭代。 - Thierry Lathuille

1

如果您尝试以下操作,可能会看到一个“超出范围”错误:

是的
my_list = [0,1,2,3,4,5]
for x in range(0, len(my_list)):
    print("Length of my_list:", len(my_list))
    my_list.pop(x)

(您还应避免使用变量名,例如list,因为它会遮盖Python内置的list。)

这更像是一个通用示例,而不是实际的代码。 - Andrew1024
你对什么说“是”? 标题中的问题的答案显然是“否”。这并没有证明range()在每次迭代时被重新评估 - 相反(因为它没有)。相反,当x变为3时,my_list中只剩下3个元素,所以弹出超出范围。迭代固定为6,迭代由错误终止,而不是通过长度的重新评估。应避免回答“是”或“否” - 问题可以很容易地改变以扭转意义。更安全的做法是清楚地陈述您所断言的内容。 - Clifford

0

请考虑以下代码:

i = 3

def test():
  global i ;
  i = i + 1
  return i

for x in range(0,test()):
  print( x, i )

每次调用`test()`时,`i`都会递增,因此如果在每次迭代中评估`test()`,则循环将无休止地进行。然而输出结果为:
0 4
1 4
2 4
3 4

因此,test()明显只会被评估一次。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接