循环完成后,Python 3 for循环索引变量值不如预期

时间:2017-09-27 07:40:11

标签: python

我试图理解Python 3在完成for循环时如何处理索引变量值。我是一名蟒蛇新手,拥有C语言的先前编程经验,所以在这一点上,我认为"在C中,尝试用Python构造等效代码。

这是一个玩具示例。 。

def tst(n): return n==6

for i in range(8,0,-1):
    if tst(i): break
print(i)

for i in range(4,0,-1):
    if tst(i): break
print(i)

第一个循环完成后,变量i的值为6,如预期的那样。

但是在第二个循环完成之后,我预计(根据我的C经验)i的值将是0(即i的最终值将落在过去范围的结束,除非有中断),但实际值为1

我希望它是0

作为替代方案,我可以用这种方式编写第二个循环:

i=4
while i>0:
   if tst(i): break
   i-=1
print(i)

以我想要的方式工作。

是这样做的吗?

更新

感谢所有人解释Python如何解释范围表达式。

使用juanpa.arrivillaga的建议,我已经解决了以下问题。 。

for i in range(4,0,-1):
    if tst(i): break
else:
    i=0
print(i)

4 个答案:

答案 0 :(得分:6)

你误解了range()是如何运作的; stop值不包含在内:

>>> list(range(4, 0, -1))
[4, 3, 2, 1]

如果您希望范围降至0,请使用-1作为结束值:

>>> list(range(4, -1, -1))
[4, 3, 2, 1, 0]

来自range() object documentation

  

对于肯定的步骤,范围r的内容由公式r[i] = start + step*i确定,其中i >= 0r[i] < stop

     

对于否定步骤,范围的内容仍由公式r[i] = start + step*i确定,但约束为i >= 0r[i] > stop

r[i] > stop表示它永远不会等于stop

您的while循环在经过测试后递减i ,因此i > 0仍适用于i = 1,但您减去了1 i = 0 1}},使其成为while,此时for测试为假,循环结束。

请注意,您无法将Python的for构造与C C进行比较。 Python概念是For each loop,而while构造实际上是 setup,test,alter 构造,它执行 setup 一次,然后重复直到测试失败,每次重复后运行 alter 指令。这就是你的i = 4循环所做的事情; 设置i > 0测试i -= 1更改指令为for at最后,在循环体的末尾。

如果你想用C语言考虑Python for循环,我能想到的最接近的是指针上的int range[] = { 4, 3, 2, 1 } for (int* p1=range; p1 < (range + (sizeof(range)/sizeof(range[0]))); p1++) { // ... } 循环:

, 0

如果您希望继续range[],则必须在0定义中添加for。 Python public class SolrData{ private int sex; @JsonSerialize(using = CustomSexSerializer.class) public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } } 循环处理任何迭代,但包括无限生成器;请参阅iterator protocol

答案 1 :(得分:4)

那是因为停止值不包括在内。这是范围的sintax:

range([start], stop[, step])

    start: Starting number of the sequence.
    stop: Generate numbers up to, but not including this number.
    step: Difference between each number in the sequence.

答案 2 :(得分:1)

以下是思考它的方法。在Python中,for循环总是迭代一组对象。循环结束时,索引变量将始终保存集合中的最后一个对象。绊倒你的是Python range()函数最后是非包容性的。请参阅https://docs.python.org/3/library/stdtypes.html#typesseq-range上的文档。

因此,在您的情况下,第二个循环正在range(4,0,-1)上正确迭代,相当于[4, 3, 2, 1],而不是[4, 3, 2, 1, 0]。因此i以该集合中的最后一个值结束,即1.如果要在范围中包含0,则必须使用range(4, -1, -1)

我发现range()的这种行为令人困惑,但它是一个非常标准的Python元素。如果你想循环重复n次,它就可以正常工作 - 只需使用range(n)来获得[0,1,...,n-1]。字符串和集合索引的工作方式类似:mystring[:4]mystring的元素4之前的提供了所有内容。如果要分割字符串,那么这种行为可能会很好:mystring[:4]为您提供前4个字符,然后mystring[4:]为您提供所有内容。这样您就不必在各个地方为索引添加1,或者记得像在C中一样使用i<3(不是i<=3)。

另一方面,如果你想要一个从1到5(含)的数字列表,你必须记住使用像range(1, 5+1)这样的东西。 (我有时会使用+1作为提醒,这会使范围进一步变大,以便range调用显示某处的实际停止点。)

答案 3 :(得分:0)

问题在于range(4,0,-1),这会返回[4, 3, 2, 1] 将其更改为range(4,-1,-1)