Pythonic way to use range excluding last number?

If I needed a list from 0 to 100 in steps of five, I could use range(0,105,5) , but I could also use range(0,101,5) .

Honestly, none of them makes sense to me, because excluding the last number seems unintuitive.

What aside, what is the β€œright” way to create a list from 0 to 100 in five steps? And if anyone has the time, in which case the exception of the last number will make the code easier to read?

+6
source share
5 answers

The two options that you indicated are not similar. One of them is range(start, stop+step, step) , and the other is range(start, stop+1, step) . They do not need to return the same. The only time they are executed is when stop - start is divided by 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] 

So which one should you use? If you want to [start, stop] (inclusive), use stop+1 to end the range. Anything greater than stop+1 will have side effects, as described above. range(0, 42+5, 5) includes 45, which is not in the range [0, 42]. What do you think about it?

+8
source

The range function works as follows:

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

This is why range(0, 105, 5) == range(0, 101, 5)

and the correct way to exclude upperBound:

 range(lowerBound, upperBound+step, step) 

From a Python document:

The full form returns a list of prime integers [start, start + step, start + 2 * step, ...].

+1
source

The correct way to create a list from 0 to 100 in five steps is

 range(0, 100, 5) 

this list has elements 100 / 5 == 20 and does not include the number 100 .

Dijkstra explained why counting should start from scratch and intervals should be half open (very?) A long time ago: https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html

Since the Python range follows Dijkstra and uses half-open intervals, in order to create one minus of the half-open interval, you must add it:

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

and, yes, I would expect to see it written in exactly the same way as in production code, since this is unusual.

+1
source

Basically, you can define your range function, including the upper value, and then use it in your code:

 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] 

EDIT

According to @ Reti43's answer, you can change this function to the following (because I think in this case, as @ Reti43 mentioned, you want to return the range (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) 
+1
source

If you want to calculate the sequence size based on the parameters to call the range () function, you must use range(0,105,5) . Consider the following:

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)

In this token you will have

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

+1
source

All Articles