Jon Gallant

How to loop over a Python range that has a single item - zero length range

2 min read

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)
```text
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](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.
```c
/* 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);
}
```text
> As Amy mentions in the comments below, this is because the `stop` parameter of the `range` 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.
```python
def lte_range_plusone(start, stop, step=1):
return range(start, stop + 1, step)
```javascript
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:
```python
def lte_range_yield(start, stop, step=1):
while start <= stop:
yield start
start += step
```text
This code will yield aka return the start value even if it is equal to the end value.
So, this code:
```python
years = lte_range_yield(2020, 2020)
for y in years:
print(y)
```text
Will output:
```bash
2020

Hope this helps you out. Let me know in the comments if you know of a better way to achieve this.

Thanks, Jon

Share:
Share on X