Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set your subtitle preferences in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please refer to our video player troubleshooting guide for assistance.

Use range() or xrange() to Track Loop Index

In the last lesson, you saw the sort of loop you might expect a developer coming from a C-style language to write in Python. In this lesson, you’ll see how you can use the range() and xrange() built-ins to make your loops more Pythonic.

The original loop keeps track of the loop index manually, which isn’t very Pythonic. You can instead keep track automatically if you use range() in Python 3 and xrange() in Python 2. A range object is a generator in Python.

00:00 The first thing I’m going to change here is how this loop was keeping track of the loop index manually—so we’re incrementing this little counter variable called i, and that’s not very Pythonic.

00:12 Thankfully, there’s a way in Python to do that automatically using the range() builtin. So in this case, I’m going to call the range() function with the length of my container—which is not ideal, just kind of foreshadowing some things, but we’re going to change that right after. So, if I call this, what I get back is a range object. Now, a range object is a generator in Python, so it’s going to be generating these individual indexes from 0 all the way to 2—because it’s not going to include the right-hand-side element.

00:44 And actually, if you want to see what this looks like, I can call list() on this range object, and that’s going to kind of go through the whole generator and it’s going to give me a list with the elements generated by the generator.

00:56 So as you can see here, this range object would go from 0 all the way to 3 - 1, which is 2. And what I can do now is I can refactor that loop using the built-in range() function, and that allows me to get rid of the index tracking.

01:13 Again, this is going to work exactly the same—what you can see here now, we’re using this range object to generate these loop indexes one by one.

01:21 Now by the way, if you’re on Python 2, you’ll want to use the xrange() builtin to actually get a generator because if you’re using range() in Python 2, it will pre-create the whole range as an actual list, which is going to be bad for memory usage. So, if you’re going to create a huge range in Python 2, this would actually pre-create all of those elements, which is probably not what you want.

01:43 So, on Python 2 you’ll want to use the xrange() builtin. It does exactly the same as range(), but the key difference is that it actually returns a generator versus returning the actual list.

jayantsing on Dec. 13, 2023

Hello, Is it possible to see an example of pre creation of list using range() in Python 2. It will be helpful to understand the difference from scratch.

Appreciate the explanation.

Dan Bader RP Team on Dec. 13, 2023

Sure thing, here’s an example! Let’s take a look at the Python 2 behavior first:

>>> # This is Python 2:
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> xrange(10)
xrange(10)

>>> list(xrange(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Now, compare this to how Python 3 behaves:

>>> # This is Python 3.11:
>>> range(10)
range(0, 10)

>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> xrange(10)
Traceback (most recent call last):
NameError: name 'xrange' is not defined. Did you mean: 'range'?

Note how range(10) returns a “pre-created” list of elements in Python 2, and a range object in Python 3.

I used a relatively short range of 0..9 here, which doesn’t really matter from a performance standpoint. But we can imagine that a huge range was used instead, like range(100000000000), where creating all those list elements would impact performance.

Become a Member to join the conversation.