我试图理解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 回答
这是考虑它的方式 . 在Python中,
for
循环总是迭代一组对象 . 循环结束时,索引变量将始终保存集合中的最后一个对象 . 绊倒你的是Pythonrange()
函数最后是非包容性的 . 请参阅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
调用显示某处的实际停止点 . )你误解了
range()
是如何工作的;stop
值不包括在内:如果要将范围降至0,请使用
-1
作为结束值:来自range() object documentation:
r[i] > stop
意味着它永远不会等于stop
.你的
while
循环递减i
after you tested it ,所以i > 0
仍然适用于i = 1
,但是你减去1
,使其成为i = 0
,此时while
测试为假并且循环结束 .请注意,您可以使用C
for
构造't really compare Python' sfor
. Python概念是For each loop,而C
构造实际上是一个setup,test,alter构造,它执行一次setup,然后重复直到测试失败,在每次重复后运行alter指令 . 这也是你的while
循环所做的;设置是i = 4
,测试是i > 0
,alter指令是你的i -= 1
,最后是循环体的末尾 .如果你想用C语言考虑Python
for
循环,我能想到的最接近的是指针上的for
循环:如果您希望它继续
0
,则必须在range[]
定义中添加, 0
. Pythonfor
循环处理任何迭代,但包括无限生成器;见iterator protocol .那个因为停止值不包括在内 . 这是范围的sintax:
你遇到的问题是
range(4,0,-1)
这会返回[4, 3, 2, 1]
将其更改为range(4,-1,-1)