为什么range(start, end)不包含end?
>>> range(1,11)
给你带来了
[1,2,3,4,5,6,7,8,9,10]
为什么不是1到11呢?
他们是随便决定这样做的,还是有什么我没看到的价值呢?
11 个回答
独占范围确实有一些好处:
首先,range(0,n)
中的每个数字都可以作为长度为n
的列表的有效索引。
另外,range(0,n)
的长度是n
,而不是像包含范围那样的n+1
。
虽然这里有一些有用的算法解释,但我觉得加上一些简单的“生活中的例子”会更有帮助,尤其是对刚接触这个话题的小朋友们来说:
比如说‘range(1,10)’,很多人会误以为这两个参数代表的是“开始和结束”。
其实它是“开始”和“停止”。
如果它真的是“结束”值,那你可能会期待这个数字会被包含在序列的最后一项里。但实际上它并不是“结束”。
还有一些人错误地称这个参数为“计数”,因为如果你只用'range(n)',那么确实会循环'n'次。但当你加上开始参数时,这种逻辑就不成立了。
所以关键是要记住它的名字:“停止”。这意味着当达到这个点时,循环会立刻停止,而不是在这个点之后再继续。
所以,“开始”确实代表了要包含的第一个值,但一旦到达“停止”值,它就会“中断”,而不是在停止之前继续处理“那个值”。
我用来给孩子们解释这个概念的一个比喻是,讽刺的是,它的表现比孩子们还要好!它不会在应该停止的时候继续 - 它会立刻停止,而不是完成正在做的事情。(他们能理解这个 ;))
另一个比喻是,当你开车时,你不会经过一个停车/让行的标志,然后让它在你车旁边或后面停下。实际上,当你停下来的时候,你并没有真正到达那个标志。它并不算在你旅途中“经过的东西”里。
希望这些能帮助解释给小朋友们听!
因为通常我们会使用 range(0, 10)
这个写法,它会返回 [0,1,2,3,4,5,6,7,8,9]
这个列表,里面有10个元素,这个数量和 len(range(0, 10))
的结果是一样的。记住,程序员习惯从0开始计数。
再看看下面这个常见的代码片段:
for i in range(len(li)):
pass
你能看到如果 range()
的结束值正好是 len(li)
,那会出问题吗?程序员就需要特别减去1。这也符合程序员的习惯,他们更喜欢写 for(int i = 0; i < 10; i++)
而不是 for(int i = 0; i <= 9; i++)
。
如果你经常用1作为 range
的起始值,可能你想自己定义一个函数:
>>> def range1(start, end):
... return range(start, end+1)
...
>>> range1(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]