Pythonic方式使用范围与排除的最后一个数字?

时间:2016-01-10 19:08:15

标签: python range

如果我想要一个从0到100的列表,以五步为单位,我可以使用range(0,105,5),但我也可以使用range(0,101,5)

老实说,这些都不合理,因为排除最后一个数字似乎不直观。

除此之外,什么是"正确的"以五步为单位创建0到100的列表的方法?如果有人有时间,在什么情况下排除最后一个数字会使代码更容易阅读?

5 个答案:

答案 0 :(得分:9)

您列出的两个选项并不相似。一个是range(start, stop+step, step),另一个是range(start, stop+1, step)。他们没有必要返回相同的东西。他们唯一的情况是stop - start可以被step整除。

>>> start, stop, step = 0, 42, 5
>>> range(start, stop+step, step)
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
>>> range(start, stop+1, step)
[0, 5, 10, 15, 20, 25, 30, 35, 40]

那么,你应该使用哪一个?如果您想要[开始,停止](包括),请使用stop+1作为范围的结尾。超过stop+1的任何内容都会产生如上所述的副作用。 range(0, 42+5, 5)包括45,因此不在[0,42]范围内。你觉得怎么样?

答案 1 :(得分:1)

range函数的工作原理如下:

i = lowerBound
while True:
     if(i < upperBound):
         range_list.append(i)
         i += step
     else:
         break

这就是range(0, 105, 5) == range(0, 101, 5)

的原因

以及排除upperBound的正确方法:

range(lowerBound, upperBound+step, step)

来自Python doc:

  

完整格式返回普通整数列表[start,start + step,   开始+ 2 *步,...]。

答案 2 :(得分:1)

以五步为单位创建从0到100的列表的正确方法是

range(0, 100, 5)

此列表包含100 / 5 == 20个元素,但不包含数字100

Dijkstra解释了为什么计数应该从零开始,间隔应该是半开(非常?)很久以前:https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html

由于Python的范围跟随Dijkstra并使用半开区间,因此要创建一个半开半区间,你必须添加一个:

range(0, 100+1, 5)  # closed interval [0..100] by five

并且,是的,我希望看到它与生产代码中的内容完全相同,因为它很不寻常。

答案 3 :(得分:1)

基本上,您可以定义范围函数,包括上限值,然后在代码中使用它:

def range_with_stop(start, stop, step):
     return range(start, stop + step, step)

In [201]: print(list(range_with_end(0, 100, 5)))
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]

编辑

根据@ Reti43的回答,您可以将该功能更改为以下(因为我认为对于那种情况,因为@Reti43提到您希望返回范围(0,40,5)):

def range_with_stop(start, stop, step):
    if stop//step == 0:
        return(range(start, stop + step, step))
    else:
        return(range(start, step * (stop//step), step))

In [265]: range_with_stop(start, 42, step)
Out[265]: range(0, 40, 5)

In [266]: range_with_stop(start, 45, step)
Out[266]: range(0, 45, 5)

答案 4 :(得分:1)

如果您希望能够根据range()函数调用的参数计算序列的大小,则应使用range(0,105,5)。请考虑以下事项:

len(range(0,6,1)) == 6 == 6/1

len(range(0,6,2)) == 3 == 6/2

len(range(0,6,3)) == 2 == 6/3

len(range(0,6,4)) == 1 == floor(6/4)

通过该令牌,您将拥有

len(range(0,105,5)) == 21 == 105/5