首页 文章

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

提问于
浏览
0

我试图理解Python 3在完成for循环时如何处理索引变量值 . 我是一个python新手,具有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)

它以我想要的方式工作 .

那是这样做的吗?

Update:

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

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

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

4 回答

  • 6

    这是考虑它的方式 . 在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 调用显示某处的实际停止点 . )

  • 1

    你误解了 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] =开始步骤* i确定,其中i> = 0并且r [i] <停止 . 对于负步骤,范围的内容仍然由公式r [i] =开始步骤* i确定,但是约束是i> = 0并且r [i]>停止 .

    r[i] > stop 意味着它永远不会等于 stop .

    你的 while 循环递减 i after you tested it ,所以 i > 0 仍然适用于 i = 1 ,但是你减去 1 ,使其成为 i = 0 ,此时 while 测试为假并且循环结束 .

    请注意,您可以使用C for 构造't really compare Python' s for . Python概念是For each loop,而 C 构造实际上是一个setup,test,alter构造,它执行一次setup,然后重复直到测试失败,在每次重复后运行alter指令 . 这也是你的 while 循环所做的;设置是 i = 4 ,测试是 i > 0 ,alter指令是你的 i -= 1 ,最后是循环体的末尾 .

    如果你想用C语言考虑Python for 循环,我能想到的最接近的是指针上的 for 循环:

    int range[] = { 4, 3, 2, 1 }
    for (int* p1=range; p1 < (range + (sizeof(range)/sizeof(range[0]))); p1++)
    {
       // ...
    }
    

    如果您希望它继续 0 ,则必须在 range[] 定义中添加 , 0 . Python for 循环处理任何迭代,但包括无限生成器;见iterator protocol .

  • 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.
    
  • 0

    你遇到的问题是 range(4,0,-1) 这会返回 [4, 3, 2, 1] 将其更改为 range(4,-1,-1)

相关问题