It is my understanding that the `range()`

function, which is actually an object type in Python 3, generates its contents on the fly, similar to a generator.

This being the case, I would have expected the following line to take an inordinate amount of time because, in order to determine whether 1 quadrillion is in the range, a quadrillion values would have to be generated:

```
1_000_000_000_000_000 in range(1_000_000_000_000_001)
```

Furthermore: it seems that no matter how many zeroes I add on, the calculation more or less takes the same amount of time (basically instantaneous).

I have also tried things like this, but the calculation is still almost instant:

```
# count by tens
1_000_000_000_000_000_000_000 in range(0,1_000_000_000_000_000_000_001,10)
```

If I try to implement my own range function, the result is not so nice!

```
def my_crappy_range(N):
i = 0
while i < N:
yield i
i += 1
return
```

What is the `range()`

object doing under the hood that makes it so fast?

Martijn Pieters’s answer was chosen for its completeness, but also see abarnert’s first answer for a good discussion of what it means for `range`

to be a full-fledged *sequence* in Python 3, and some information/warning regarding potential inconsistency for `__contains__`

function optimization across Python implementations. abarnert’s other answer goes into some more detail and provides links for those interested in the history behind the optimization in Python 3 (and lack of optimization of `xrange`

in Python 2). by poke and by wim provide the relevant C source code and explanations for those who are interested.