Python 为什么 range(start, end) 不包括 end?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4504662/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does range(start, end) not include end?
提问by MetaGuru
>>> range(1,11)
gives you
给你
[1,2,3,4,5,6,7,8,9,10]
Why not 1-11?
为什么不是 1-11?
Did they just decide to do it like that at random or does it have some value I am not seeing?
他们是随机决定这样做还是有一些我没有看到的价值?
采纳答案by moinudin
Because it's more common to call range(0, 10)which returns [0,1,2,3,4,5,6,7,8,9]which contains 10 elements which equals len(range(0, 10)). Remember that programmers prefer 0-based indexing.
因为更常见的是调用range(0, 10)which 返回[0,1,2,3,4,5,6,7,8,9]包含 10 个等于 的元素len(range(0, 10))。请记住,程序员更喜欢基于 0 的索引。
Also, consider the following common code snippet:
另外,请考虑以下常见代码片段:
for i in range(len(li)):
pass
Could you see that if range()went up to exactly len(li)that this would be problematic? The programmer would need to explicitly subtract 1. This also follows the common trend of programmers preferring for(int i = 0; i < 10; i++)over for(int i = 0; i <= 9; i++).
你能看到,如果range()上升到len(li)这一点,这将是有问题的吗?程序员需要显式减1。这也遵循程序员喜欢的共同趋势for(int i = 0; i < 10; i++)了for(int i = 0; i <= 9; i++)。
If you are calling range with a start of 1 frequently, you might want to define your own function:
如果您经常调用以 1 开头的 range,您可能需要定义自己的函数:
>>> def range1(start, end):
... return range(start, end+1)
...
>>> range1(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
回答by Skilldrick
The length of the range is the top value minus the bottom value.
范围的长度是顶部值减去底部值。
It's very similar to something like:
它与以下内容非常相似:
for (var i = 1; i < 11; i++) {
//i goes from 1 to 10 in here
}
in a C-style language.
在 C 风格的语言中。
Also like Ruby's range:
也喜欢 Ruby 的范围:
1...11 #this is a range from 1 to 10
However, Ruby recognises that many times you'll want to include the terminal value and offers the alternative syntax:
但是,Ruby 认识到很多时候您需要包含终端值并提供替代语法:
1..10 #this is also a range from 1 to 10
回答by sepp2k
Exclusive ranges do have some benefits:
独家范围确实有一些好处:
For one thing each item in range(0,n)is a valid index for lists of length n.
一方面,其中的每个项目range(0,n)都是 length 列表的有效索引n。
Also range(0,n)has a length of n, not n+1which an inclusive range would.
也range(0,n)有长度n,不是n+1包含范围的长度。
回答by kindall
It works well in combination with zero-based indexing and len(). For example, if you have 10 items in a list x, they are numbered 0-9. range(len(x))gives you 0-9.
它与基于零的索引和len(). 例如,如果列表中有 10 个项目x,它们的编号为 0-9。range(len(x))给你 0-9。
Of course, people will tell you it's more Pythonic to do for item in xor for index, item in enumerate(x)rather than for i in range(len(x)).
当然,人们会告诉你,它更像是 Pythonicfor item in x或for index, item in enumerate(x)而不是for i in range(len(x)).
Slicing works that way too: foo[1:4]is items 1-3 of foo(keeping in mind that item 1 is actually the second item due to the zero-based indexing). For consistency, they should both work the same way.
切片也是这样工作的:foo[1:4]是第 1-3 项foo(请记住,由于基于零的索引,第 1 项实际上是第二项)。为了一致性,它们都应该以相同的方式工作。
I think of it as: "the first number you want, followed by the first number you don'twant." If you want 1-10, the first number you don't want is 11, so it's range(1, 11).
我认为它是:“你想要的第一个数字,然后是你不想要的第一个数字。” 如果你想要 1-10,你不想要的第一个数字是 11,所以它是range(1, 11).
If it becomes cumbersome in a particular application, it's easy enough to write a little helper function that adds 1 to the ending index and calls range().
如果它在特定应用程序中变得很麻烦,那么编写一个小辅助函数将 1 添加到结束索引并调用range().
回答by Robert
Consider the code
考虑代码
for i in range(10):
print "You'll see this 10 times", i
The idea is that you get a list of length y-x, which you can (as you see above) iterate over.
这个想法是你得到一个 length 列表y-x,你可以(如上所见)迭代它。
Read up on the python docsfor range - they consider for-loop iteration the primary usecase.
阅读Python 文档的范围 - 他们认为 for-loop 迭代是主要用例。
回答by xuanji
It's also useful for splitting ranges; range(a,b)can be split into range(a, x)and range(x, b), whereas with inclusive range you would write either x-1or x+1. While you rarely need to split ranges, you do tend to split lists quite often, which is one of the reasons slicing a list l[a:b]includes the a-th element but not the b-th. Then rangehaving the same property makes it nicely consistent.
它对于分割范围也很有用;range(a,b)可以拆分为range(a, x)and range(x, b),而对于包含范围,您可以编写x-1or x+1。虽然您很少需要拆分范围,但您确实倾向于经常拆分列表,这就是切片l[a:b]包含第 a 个元素而不包含第 b 个元素的原因之一。然后range具有相同的属性使其非常一致。
回答by dingles
Although there are some useful algorithmic explanations here, I think it may help to add some simple 'real life' reasoning as to why it works this way, which I have found useful when introducing the subject to young newcomers:
虽然这里有一些有用的算法解释,但我认为添加一些简单的“现实生活”推理可能有助于解释为什么它会以这种方式工作,我在向年轻新人介绍这个主题时发现这很有用:
With something like 'range(1,10)' confusion can arise from thinking that pair of parameters represents the "start and end".
像“范围(1,10)”这样的东西可能会产生混淆,因为认为这对参数代表“开始和结束”。
It is actually start and "stop".
它实际上是开始和“停止”。
Now, if it werethe "end" value then, yes, you might expect that number would be included as the final entry in the sequence. But it is not the "end".
现在,如果它是“结束”值,那么,是的,您可能希望该数字将作为序列中的最后一个条目包含在内。但这不是“结束”。
Others mistakenly call that parameter "count" because if you only ever use 'range(n)' then it does, of course, iterate 'n' times. This logic breaks down when you add the start parameter.
其他人错误地将该参数称为“计数”,因为如果您只使用 'range(n)' 那么它当然会迭代 'n' 次。当您添加 start 参数时,此逻辑会失效。
So the key point is to remember its name: "stop". That means it is the point at which, when reached, iteration will stop immediately. Not afterthat point.
所以关键是要记住它的名字:“停止”。这意味着当到达时,迭代将立即停止。不是在那之后。
So, while "start" does indeed represent the first value to be included, on reaching the "stop" value it 'breaks' rather than continuing to process 'that one as well' before stopping.
因此,虽然“开始”确实表示要包含的第一个值,但在达到“停止”值时它会“中断”,而不是在停止之前继续处理“那个”。
One analogy that I have used in explaining this to kids is that, ironically, it is better behaved than kids! It doesn't stop afterit supposed to - it stops immediately without finishing what it was doing. (They get this ;) )
我用来向孩子们解释这一点的一个类比是,具有讽刺意味的是,它比孩子们表现得更好!它不会在它应该停止之后停止——它没有完成它正在做的事情就立即停止。(他们得到这个;))
Another analogy - when you drive a car you don't passa stop/yield/'give way' sign and end up with it sitting somewhere next to, or behind, your car. Technically you still haven't reached it when you do stop. It is not included in the 'things you passed on your journey'.
另一个类比——当你开车时,你不会通过一个停车/让路/“让路”标志,最终它坐在你的车旁边或后面的某个地方。从技术上讲,当您停下来时,您还没有达到它。它不包括在“您在旅途中传递的东西”中。
I hope some of that helps in explaining to Pythonitos/Pythonitas!
我希望其中一些有助于向 Pythonitos/Pythonitas 解释!
回答by Ashish Dixit
Basically in python range(n)iterates ntimes, which is of exclusive nature that is why it does not give last value when it is being printed, we can create a function which gives
inclusive value it means it will also print last value mentioned in range.
基本上在python中range(n)迭代n次数,这是排他性的,这就是为什么它在打印时不给出最后一个值,我们可以创建一个给出包含值的函数,这意味着它也将打印范围中提到的最后一个值。
def main():
for i in inclusive_range(25):
print(i, sep=" ")
def inclusive_range(*args):
numargs = len(args)
if numargs == 0:
raise TypeError("you need to write at least a value")
elif numargs == 1:
stop = args[0]
start = 0
step = 1
elif numargs == 2:
(start, stop) = args
step = 1
elif numargs == 3:
(start, stop, step) = args
else:
raise TypeError("Inclusive range was expected at most 3 arguments,got {}".format(numargs))
i = start
while i <= stop:
yield i
i += step
if __name__ == "__main__":
main()
回答by Arseny
It's just more convenient to reason about in many cases.
在许多情况下,推理更方便。
Basically, we could think of a range as an interval between startand end. If start <= end, the length of the interval between them is end - start. If lenwas actually defined as the length, you'd have:
基本上,我们可以将范围视为start和之间的间隔end。如果start <= end,它们之间的间隔长度为end - start。如果len实际上定义为长度,则您将拥有:
len(range(start, end)) == start - end
However, we count the integers included in the range instead of measuring the length of the interval. To keep the above property true, we should include one of the endpoints and exclude the other.
但是,我们计算范围内包含的整数,而不是测量间隔的长度。为了保持上述属性为真,我们应该包括一个端点并排除另一个端点。
Adding the stepparameter is like introducing a unit of length. In that case, you'd expect
添加step参数就像引入一个长度单位。在那种情况下,你会期望
len(range(start, end, step)) == (start - end) / step
for length. To get the count, you just use integer division.
为长度。要获得计数,您只需使用整数除法。

