I’m working on an app that accepts user input of a start year and end year, loops through those years, and outputs the year.
For example, given the start year and end year of 2020, I want a loop to execute for 2020.
years = range(2020, 2020)
for y in years:
print(y)
But the python range
object doesn’t recognize this as a single range item and won’t output anything. The source for the range object is here: https://github.com/python/cpython/blob/master/Objects/rangeobject.c and I believe it is this conditional statement that causes range to return a length of zero.
/* if (lo >= hi), return length of 0. */
cmp_result = PyObject_RichCompareBool(lo, hi, Py_GE);
if (cmp_result != 0) {
Py_DECREF(step);
if (cmp_result < 0)
return NULL;
return PyLong_FromLong(0);
}
As Amy mentions in the comments below, this is because the
stop
parameter of therange
object is exclusive - meaning it does a < compare, not a <= compare. So a great option is to always just add 1 to the stop parameter to include it.
def lte_range_plusone(start, stop, step=1):
return range(start, stop + 1, step)
An alternate solution to this was to create a custom function that uses the python yield
keyword to return an item even if the start and end are equal, with this code:
def lte_range_yield(start, stop, step=1):
while start <= stop:
yield start
start += step
This code will yield aka return the start value even if it is equal to the end value.
So, this code:
years = lte_range_yield(2020, 2020)
for y in years:
print(y)
Will output:
2020
Hope this helps you out. Let me know in the comments if you know of a better way to achieve this.
Thanks,
Jon