问题:为什么范围(开始,结束)不包括结束?
>>> range(1,11)
给你
[1,2,3,4,5,6,7,8,9,10]
为什么不选择1-11?
他们是只是决定随机地这样做,还是有一些我没有看到的价值?
回答 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]
回答 1
尽管这里有一些有用的算法解释,但我认为添加一些简单的“现实生活”推理可能会有助于以这种方式工作,这对我向年轻新手介绍该主题很有用:
对于“ range(1,10)”之类的东西,可能会因认为一对参数代表“开始和结束”而产生混淆。
它实际上是开始和“停止”。
现在,如果它是 “结束”值,是的,您可能希望该数字将作为序列中的最后一个条目包括在内。但这不是“终点”。
其他人错误地将该参数称为“ count”,因为如果您只使用“ range(n)”,那么它当然会迭代“ n”次。添加开始参数时,此逻辑将失效。
因此,关键是要记住它的名称:“ stop ”。这意味着到达该点时,迭代将立即停止。不经过这一点。
因此,虽然“开始”确实代表要包含的第一个值,但在达到“停止”值时,它“中断”而不是在停止之前继续处理“该一个”。
我用来向孩子们解释的一个比喻是,具有讽刺意味的是,它比孩子们表现得更好!它不会在应有的状态下停止-它会在未完成操作的情况下立即停止。(他们得到这个;)
另一个比喻-当您开车时,您不会通过停车/屈服/“放弃”标志,而最终会停在您的汽车旁边或后面。从技术上讲,您停止时仍未达到目标。它不包含在“您在旅途中传递的事物”中。
我希望其中一些有助于解释Pythonitos / Pythonitas!
回答 2
互斥范围确实有一些好处:
一方面,每一项range(0,n)
都是长度列表的有效索引n
。
还range(0,n)
具有的长度n
,不是n+1
包含范围的长度。
回答 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()
。
回答 4
这对于分割范围也很有用;range(a,b)
可以分为range(a, x)
和range(x, b)
,而在包含范围内,您可以编写x-1
或x+1
。尽管您几乎不需要拆分范围,但您确实倾向于拆分列表,这是对列表进行切片的原因之一,其中l[a:b]
包括第a个元素,但不包括第b个元素。然后range
具有相同的属性使其完全一致。
回答 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
回答 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()
回答 7
考虑代码
for i in range(10):
print "You'll see this 10 times", i
想法是获得一个length的列表y-x
,您可以(如上所述)进行迭代。
阅读有关范围的python文档 -他们将for循环迭代视为主要用例。
回答 8
在许多情况下,这样做更方便。
基本上,我们可以将范围视为start
和之间的间隔end
。如果是start <= end
,则它们之间的间隔长度为end - start
。如果len
实际定义为长度,则将具有:
len(range(start, end)) == start - end
但是,我们计算范围内包含的整数,而不是测量间隔的长度。为了保持上述属性为真,我们应包括一个端点,而排除另一个端点。
添加step
参数就像引入长度单位一样。在这种情况下,您会期望
len(range(start, end, step)) == (start - end) / step
对于长度。要获得计数,您只需使用整数除法。