为什么range(start, end)不包含end?

424 投票
11 回答
508162 浏览
提问于 2025-04-16 08:52
>>> range(1,11)

给你带来了

[1,2,3,4,5,6,7,8,9,10]

为什么不是1到11呢?

他们是随便决定这样做的,还是有什么我没看到的价值呢?

11 个回答

27

独占范围确实有一些好处:

首先,range(0,n)中的每个数字都可以作为长度为n的列表的有效索引。

另外,range(0,n)的长度是n,而不是像包含范围那样的n+1

86

虽然这里有一些有用的算法解释,但我觉得加上一些简单的“生活中的例子”会更有帮助,尤其是对刚接触这个话题的小朋友们来说:

比如说‘range(1,10)’,很多人会误以为这两个参数代表的是“开始和结束”。

其实它是“开始”和“停止”。

如果它真的是“结束”值,那你可能会期待这个数字会被包含在序列的最后一项里。但实际上它并不是“结束”。

还有一些人错误地称这个参数为“计数”,因为如果你只用'range(n)',那么确实会循环'n'次。但当你加上开始参数时,这种逻辑就不成立了。

所以关键是要记住它的名字:“停止”。这意味着当达到这个点时,循环会立刻停止,而不是这个点之后再继续。

所以,“开始”确实代表了要包含的第一个值,但一旦到达“停止”值,它就会“中断”,而不是在停止之前继续处理“那个值”。

我用来给孩子们解释这个概念的一个比喻是,讽刺的是,它的表现比孩子们还要好!它不会在应该停止的时候继续 - 它会立刻停止,而不是完成正在做的事情。(他们能理解这个 ;))

另一个比喻是,当你开车时,你不会经过一个停车/让行的标志,然后让它在你车旁边或后面停下。实际上,当你停下来的时候,你并没有真正到达那个标志。它并不算在你旅途中“经过的东西”里。

希望这些能帮助解释给小朋友们听!

319

因为通常我们会使用 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]

撰写回答