4) d. Range Function

One of the areas that confuses people in Python 3 is range, especially if you are coming from Python 2 or if you’re participating in any online discussions.

You will frequently find talk about xrange and range online without any mention of the Python version. Some tell you that xrange is better than range while others will insist on the opposite.

Hence, it is important that you know the backstory of the range function so that you can remain confident when they’re talking about it.

In Python 3, we only have the range function. Period. So we have:

Python 2: range, and xrange (their differences are discussed below)
Python 3: (the old range has been removed, and the old xrange is now called as range in Python 3).

Let us first try to understand the difference between both the functions in Python 2, which will bring us a better appreciation of Python 3’s range.

Python 2 provided both, the range and xrange functions which allowed us to generate a series of numbers. Both gave the same output. The difference was in how much memory they consumed.

Consider the following piece of code written in Python 2:

1
print(range(10))
1
2
Output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

No surprise so far.

But imagine if the number being passed was fantastically large. Consider this example (Python 2).

1
2
3
4
5
6
7
8
9
10
size = 1000000000 #Large value
limit = 50

for i in range(size):  # A lot of memory!
    # Do something useful with i...
    if i > limit:
        print("Work done")
        break

#Notice that our code only utilizes the first 50 values

The range function generates a huge amount of values. But we only need the first 50 values. When our work is done with these 50 values we break the loop.

Pause for a moment right here. Can you guess what’s the issue here? There are two.

Firstly, we are generating a huge list (which contains 1000000000 values). This consumes a huge amount of memory and might even crash the program with an “out of memory” error depending on how much RAM is available.


Secondly, even if we have enough memory in our system, we are only interested in the first 50 elements. All elements generated beyond 50 are useless and take up both CPU + memory.

So how can we solve this problem? This is where the Python 2’s xrange function comes in.

Instead of creating a list and populating it with a billion elements it will generate only a single value – the current value which is being accessed in the loop. Because of this kind of implementation, xrange takes up very little memory. You can stop the loop at any point and no further values will get generated. This saves your memory and CPU usage, thereby making your program more efficient.

xrange is an example of a generator. Later in this course you will learn more about them, their advantages and disadvantages and how to create them yourself.

So what happened to xrange in Python 3? The old implementation of xrange from Python 2 was renamed to range in Python 3.

That means that when you’re using Python 3 no matter how big of a range you want to iterate through the values will only be generated when you actually use them.

And when you read online people saying that “xrange is better than range” you’ll know that they’re talking about Python 2. There is no xrange in Python 3.