问题:为什么范围(开始,结束)不包括结束?
>>> range(1,11)
给你
[1,2,3,4,5,6,7,8,9,10]
为什么不选择1-11?
他们是只是决定随机地这样做,还是有一些我没有看到的价值?
>>> range(1,11)
gives you
[1,2,3,4,5,6,7,8,9,10]
Why not 1-11?
Did they just decide to do it like that at random or does it have some value I am not seeing?
回答 0
因为调用range(0, 10)
return [0,1,2,3,4,5,6,7,8,9]
包含10个等于equals的元素更为常见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]
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.
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++)
.
If you are calling range with a start of 1 frequently, you might want to define your own function:
>>> def range1(start, end):
... return range(start, end+1)
...
>>> range1(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
回答 1
尽管这里有一些有用的算法解释,但我认为添加一些简单的“现实生活”推理可能会有助于以这种方式工作,这对我向年轻新手介绍该主题很有用:
对于“ range(1,10)”之类的东西,可能会因认为一对参数代表“开始和结束”而产生混淆。
它实际上是开始和“停止”。
现在,如果它是 “结束”值,是的,您可能希望该数字将作为序列中的最后一个条目包括在内。但这不是“终点”。
其他人错误地将该参数称为“ count”,因为如果您只使用“ range(n)”,那么它当然会迭代“ n”次。添加开始参数时,此逻辑将失效。
因此,关键是要记住它的名称:“ stop ”。这意味着到达该点时,迭代将立即停止。不经过这一点。
因此,虽然“开始”确实代表要包含的第一个值,但在达到“停止”值时,它“中断”而不是在停止之前继续处理“该一个”。
我用来向孩子们解释的一个比喻是,具有讽刺意味的是,它比孩子们表现得更好!它不会在应有的状态下停止-它会在未完成操作的情况下立即停止。(他们得到这个;)
另一个比喻-当您开车时,您不会通过停车/屈服/“放弃”标志,而最终会停在您的汽车旁边或后面。从技术上讲,您停止时仍未达到目标。它不包含在“您在旅途中传递的事物”中。
我希望其中一些有助于解释Pythonitos / Pythonitas!
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”.
It is actually start and “stop”.
Now, if it were the “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.
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 after that 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 after it supposed to – it stops immediately without finishing what it was doing. (They get this ;) )
Another analogy – when you drive a car you don’t pass a 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!
回答 2
互斥范围确实有一些好处:
一方面,每一项range(0,n)
都是长度列表的有效索引n
。
还range(0,n)
具有的长度n
,不是n+1
包含范围的长度。
Exclusive ranges do have some benefits:
For one thing each item in range(0,n)
is a valid index for lists of length n
.
Also range(0,n)
has a length of n
, not n+1
which an inclusive range would.
回答 3
与基于零的索引和结合使用时效果很好len()
。例如,如果列表中有10个项目x
,则它们的编号为0-9。range(len(x))
给你0-9。
当然,人们会告诉你这是更Python做for item in x
或for index, item in enumerate(x)
不是for i in range(len(x))
。
切片也是如此:foo[1:4]
是项的1-3 foo
(请记住,由于从零开始的索引,项1实际上是第二项)。为了保持一致,它们都应以相同的方式工作。
我认为它是:“您想要的第一个数字,然后是您不需要的第一个数字。” 如果您想要1-10,则您不希望的第一个数字是11,所以它是range(1, 11)
。
如果它在特定的应用程序中变得繁琐,那么编写一个简单的辅助函数就很容易了,该函数将1加到结束索引并调用range()
。
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.
Of course, people will tell you it’s more Pythonic to do for item in x
or for index, item in enumerate(x)
rather than 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.
I think of it as: “the first number you want, followed by the first number you don’t want.” If you want 1-10, the first number you don’t want is 11, so it’s 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()
.
回答 4
这对于分割范围也很有用;range(a,b)
可以分为range(a, x)
和range(x, b)
,而在包含范围内,您可以编写x-1
或x+1
。尽管您几乎不需要拆分范围,但您确实倾向于拆分列表,这是对列表进行切片的原因之一,其中l[a:b]
包括第a个元素,但不包括第b个元素。然后range
具有相同的属性使其完全一致。
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-1
or 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 range
having the same property makes it nicely consistent.
回答 5
范围的长度是上限值减去下限值。
它非常类似于以下内容:
for (var i = 1; i < 11; i++) {
//i goes from 1 to 10 in here
}
用C风格的语言。
也像Ruby的范围:
1...11 #this is a range from 1 to 10
但是,Ruby认识到很多时候您都想包含终端值,并提供了另一种语法:
1..10 #this is also a range from 1 to 10
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.
Also like Ruby’s range:
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:
1..10 #this is also a range from 1 to 10
回答 6
基本上在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()
Basically in python range(n)
iterates n
times, 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.
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()
回答 7
考虑代码
for i in range(10):
print "You'll see this 10 times", i
想法是获得一个length的列表y-x
,您可以(如上所述)进行迭代。
阅读有关范围的python文档 -他们将for循环迭代视为主要用例。
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.
Read up on the python docs for range – they consider for-loop iteration the primary usecase.
回答 8
在许多情况下,这样做更方便。
基本上,我们可以将范围视为start
和之间的间隔end
。如果是start <= end
,则它们之间的间隔长度为end - start
。如果len
实际定义为长度,则将具有:
len(range(start, end)) == start - end
但是,我们计算范围内包含的整数,而不是测量间隔的长度。为了保持上述属性为真,我们应包括一个端点,而排除另一个端点。
添加step
参数就像引入长度单位一样。在这种情况下,您会期望
len(range(start, end, step)) == (start - end) / step
对于长度。要获得计数,您只需使用整数除法。
It’s just more convenient to reason about in many cases.
Basically, we could think of a range as an interval between start
and end
. If start <= end
, the length of the interval between them is end - start
. If len
was actually defined as the length, you’d have:
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 step
parameter is like introducing a unit of length. In that case, you’d expect
len(range(start, end, step)) == (start - end) / step
for length. To get the count, you just use integer division.