# Allow \`range(start, None, step)\` for an endless range

**URL:** <https://discuss.python.org/t/allow-range-start-none-step-for-an-endless-range/6668>\
**Category:** Ideas\
**Created:** [January 15, 2021, 12:28pm UTC](https://discuss.python.org/t/allow-range-start-none-step-for-an-endless-range/6668 "2021-01-15T12:28:01Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![TomFryers](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/tomfryers/32/11086_2.png) [@TomFryers](https://discuss.python.org/u/TomFryers)\
**Post date:** [January 15, 2021, 12:28pm UTC](https://discuss.python.org/t/allow-range-start-none-step-for-an-endless-range/6668/1 "2021-01-15T12:28:01Z")

</div>

Currently, to iterate over finite arithmetic sequences of integers, `range` is used, as in:

```python
for i in range(10):
    print(i)

```

For an _infinite_ arithmetic sequence, there are a few approaches. One can replace the ‘10’ with a long sequence of nines, write a generator function or just switch to a while loop, but the current ‘best’ way is using itertools:

```python
import itertools
for i in itertools.count():
    print(i)

```

There are a few downsides to this. Firstly, `itertools.count` is doing a very similar thing to `range`, yet seems on first glance completely unrelated. Without knowing, it’s easy to assume that `itertools.count` does a similar thing to `list.count` or `str.count`, rather than `range`.

In some other languages the finite and infinite cases look very similar, C (and other languages with the same loop syntax) and Rust being two examples.

Secondly, infinite loops like this are quite common in tiny example programs, e.g.

```python
import itertools
primes = []
for i in itertools.count(2):
    if all(i % p for p in primes):
        primes.append(i)
        print(i)

```

In these cases, having to import itertools to get an infinite loop makes the program significantly longer.

I propose using `range(start, None, step)` for an endless range. This makes sense, as the ‘stop’ parameter is None, i.e. there is no ‘stop’ and the iterable goes on forever. The `step` and `start` parameters could be omitted as normal.

I would also suggest `range()` should default to an end of `None` with zero arguments:

```python
for i in range():
    print(i)

```

Downsides:

- Performance hit (probably tiny) on finite loops
- `len` of a range is no longer always nice
- More ways to do the same thing (perhaps deprecate `itertools.count`?)

---

<div class="post-metadata">

**Author:** ![ericvsmith](https://avatars.discourse-cdn.com/v4/letter/e/34f0e0/32.png) [@ericvsmith](https://discuss.python.org/u/ericvsmith)\
**Post date:** [January 15, 2021, 12:37pm UTC](https://discuss.python.org/t/allow-range-start-none-step-for-an-endless-range/6668/2 "2021-01-15T12:37:23Z")

</div>

> [@TomFryers](#):
>
> The `step` and `start` parameters could be omitted as normal.

I would not want `range(None)` to be valid. There’s too much of a chance for an error to creep in. `range(some_function())`. What if some\_function accidentally returned None? Now it’s an infinite loop.

Otherwise I’m -0. I don’t think itertools.count is too hard to find.

---

<div class="post-metadata">

**Author:** ![TomFryers](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/tomfryers/32/11086_2.png) [@TomFryers](https://discuss.python.org/u/TomFryers)\
**Post date:** [January 15, 2021, 12:43pm UTC](https://discuss.python.org/t/allow-range-start-none-step-for-an-endless-range/6668/3 "2021-01-15T12:43:09Z")

</div>

Yes, that makes sense. I’ve just managed to find [this discussion](https://mail.python.org/archives/list/python-ideas@python.org/thread/6WEV73JM4EARGAYT6JIFH35Y5MRLK3MX/#KYDECOSQCTAE5QJN5HJICZBJVUNQ45CB), which didn’t really seem to go anywhere. The suggestion there was using `...` (i.e. `Ellipsis`) instead of `None`, which might be better.

---

<div class="post-metadata">

**Author:** ![aroberge](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/aroberge/32/6200_2.png) [@aroberge](https://discuss.python.org/u/aroberge)\
**Post date:** [January 15, 2021, 1:58pm UTC](https://discuss.python.org/t/allow-range-start-none-step-for-an-endless-range/6668/4 "2021-01-15T13:58:48Z")

</div>

Just use a `while` loop with an explicit counter.

```python
i = 0
while True:
    do_whatever()
    i += 1

```

---

<div class="post-metadata">

**Author:** ![steven.daprano](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steven.daprano/32/1083_2.png) [@steven.daprano](https://discuss.python.org/u/steven.daprano)\
**Post date:** [January 17, 2021, 3:19am UTC](https://discuss.python.org/t/allow-range-start-none-step-for-an-endless-range/6668/5 "2021-01-17T03:19:03Z")

</div>

I know it sounds odd to worry about performance of an infinite loop (“my  
code is so fast it can run an infinite loop in 20 microseconds!”) but  
there are cases where you exit out of the loop and performance matters.

In those cases, itertools.count is faster and more efficient, and  
cleaner too, as you don’t have to worry about manually updating the  
counter.

---

<div class="post-metadata">

**Author:** ![mattip](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mattip/32/330_2.png) [@mattip](https://discuss.python.org/u/mattip)\
**Post date:** [January 17, 2021, 7:40am UTC](https://discuss.python.org/t/allow-range-start-none-step-for-an-endless-range/6668/6 "2021-01-17T07:40:27Z")

</div>

The fact that itertools.count is marginally faster than explicitly incrementing a counter is a CPython implementation detail due to itertools being implemented as a c-extension module. I don’t know if that is true when the code is transpiled for cython, numba or pythran. I am pretty sure in PyPy it will be slower, since in general itertools is slower on PyPy than an explicit implementation due to the extra indirection.

---

<div class="post-metadata">

**Author:** ![ruud](https://avatars.discourse-cdn.com/v4/letter/r/838e76/32.png) [@ruud](https://discuss.python.org/u/ruud)\
**Post date:** [January 18, 2021, 7:45am UTC](https://discuss.python.org/t/allow-range-start-none-step-for-an-endless-range/6668/7 "2021-01-18T07:45:11Z")

</div>

I really like your proposal.  
I know about `itertools.count`, but find it confusing and quite cumbersome to import just for that.  
I don’t think there are any real disadvantages:

- **performance**. Very unlikely to be significant
- **implementation** of len. Just a `NotImplemented` exception could be raised
- **duplicate functionality** There are so many cases of that in Python, that it can’t be a serious problem. Please don’t deprecate `itertools.count`

---

<div class="post-metadata">

**Author:** ![mehaase](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mehaase/32/378_2.png) [@mehaase](https://discuss.python.org/u/mehaase)\
**Post date:** [January 20, 2021, 10:10pm UTC](https://discuss.python.org/t/allow-range-start-none-step-for-an-endless-range/6668/8 "2021-01-20T22:10:21Z")

</div>

“Endless range” is an oxymoron (by definition a range has endpoints) while itertools.count does exactly what it sounds like. You also won’t find much support for deprecating something in itertools that already works well and is widely used.

If this is for teaching purposes, I think you already landed on the right solution. The upper end of the range should be some really large number, perhaps `10**20` or a named constant like `sys.maxsize`. The practical difference between running forever and running for several millennia doesn’t seem like a big deal. Plus, you can use this as a motivating example for students to learn generators.

---

<div class="post-metadata">

**Author:** ![steven.daprano](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steven.daprano/32/1083_2.png) [@steven.daprano](https://discuss.python.org/u/steven.daprano)\
**Post date:** [January 21, 2021, 9:31am UTC](https://discuss.python.org/t/allow-range-start-none-step-for-an-endless-range/6668/9 "2021-01-21T09:31:18Z")

</div>

Mark said:

“Endless range” is an oxymoron (by definition a range has endpoints)

I think mathematicians will disagree.

> **[Range of a function](https://en.wikipedia.org/wiki/Range_of_a_function)**
>
> In mathematics, the range of a function may refer to either of two closely related concepts:
> As the term "range" can have different meanings, it is considered a good practice to define it the first time it is used in a textbook or article. Older books, when they use the word "range", tend to use it to mean what is now called the codomain. More modern books, if they use the word "range" at all, generally use it to mean what is now called the image. To avoid any confusion, a number of modern boo...

Both the codomain and image can be infinite in either direction, or  
both.

So does Ruby:

[https://ruby-doc.org/core-2.6/Range.html#class-Range-label-Endless+Ranges](https://ruby-doc.org/core-2.6/Range.html#class-Range-label-Endless+Ranges)

And of course, in common English parlance, we can talk about ice cream  
that comes in an endless range of flavours, shops that stock an endless  
range of parts, and holiday parks that offer an endless range of fun  
activities. And of course, there is the iconic American image of the  
lone cowboy riding riding across the endless range.

Some downsides of itertools.count:

- Its not a sequence like range;
- and membership testing consumes values.

On the other hand, it does support arbitrary step sizes.

---

<div class="post-metadata">

**Author:** ![pf\_moore](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pf_moore/32/35_2.png) [@pf\_moore](https://discuss.python.org/u/pf_moore)\
**Post date:** [January 21, 2021, 9:52am UTC](https://discuss.python.org/t/allow-range-start-none-step-for-an-endless-range/6668/10 "2021-01-21T09:52:46Z")

</div>

> [@steven.daprano](#):
>
> Some downsides of itertools.count:
> 
> - Its not a sequence like range;
> - and membership testing consumes values.
> 
> On the other hand, it does support arbitrary step sizes.

And of course, the problem with the original proposal that `range(start, None, step)` should give an endless range, is precisely that this would mean that range objects could no longer be sequences either (from `collections.abc`, objects that implement `Sequence` must be sized and reversible, neither of which can be true for infinite ranges).

Whether this is important in practice, is an open question, of course, but note that the following works with range objects at the moment:

```python
>>> range(10)[2:-1]
range(2, 9)
>>> range(10)[2:-1:-1]
range(2, 9, -1)

```

With infinite ranges, that’s no longer possible. And before anyone suggests it, I really don’t like the idea of range objects that _might_ support `Sequence` operations, depending on the arguments used to create them…

It’s not _that_ hard to use `itertools.count`, or write your own infinite generator, so I don’t think the trade-offs for this proposal are worth it.

---

<div class="post-metadata">

**Author:** ![mehaase](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mehaase/32/378_2.png) [@mehaase](https://discuss.python.org/u/mehaase)\
**Post date:** [January 21, 2021, 4:04pm UTC](https://discuss.python.org/t/allow-range-start-none-step-for-an-endless-range/6668/11 "2021-01-21T16:04:21Z")

</div>

> [@steven.daprano](#):
>
> I think mathematicians will disagree.
> 
> [Range of a function](https://en.wikipedia.org/wiki/Range_of_a_function)

Of course words have multiple meanings, but the specific meaning of `range()` in Python is clearly not referring to the codomain of a mathematical function. [The dictionary](https://www.merriam-webster.com/dictionary/range) offers the following:

> a sequence, series, or scale between limits

You might argue that “limit” does not necessarily imply _finite_ limits, and since I don’t think further debate about the semantics of the English language is productive, I won’t belabor the point.

I am a bit surprised that `range(2, math.inf)` does not work, but that seems like a more promising approach for infinite ranges than overloading `None` to mean “no upper limit”.

---

<div class="post-metadata">

**Author:** ![davidism](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/davidism/32/3295_2.png) [@davidism](https://discuss.python.org/u/davidism)\
**Post date:** [August 24, 2026, 2:23pm UTC](https://discuss.python.org/t/allow-range-start-none-step-for-an-endless-range/6668/13 "2026-08-24T14:23:31Z")

</div>


