# Python Ranges

If you've used Python for any length of time on the Pi, it's almost certain that you've come across `range`. Python's range is simply that: a range of values meeting certain criteria.

Range accepts three arguments:

• Start - The number to start from
• Stop - The number to stop at, not included in the range
• Step - The step size of the range

## Differences between Python 2 and Python 3

Range is one of the many gotchas in the transition between Python 2 and 3. Here's why:

### In Python 2 a range returns a list:

``````>>> range(0,5)
[0, 1, 2, 3, 4]
``````

In Python 2, the range function will immediately figure out every single number contained within the range you've asked for and will return it as a list.

### In Python 3 a range returns an "virtual sequence of numbers":

``````>>> range(0,5)
range(0, 5)
``````

Seeing the Python 2 method as wasteful, Python 3 changed range to use the "lazy way." Python 3's lazy ranges will only give you a value when asked for it, so if you do this:

``````>>> my_range = range(0,5)
>>> do_something_completely_different()
``````

Python 3 simply wont waste time figuring out the values in `my_range`. In Python 2, however, it will go off and create a list at its leisure.

In most cases, you'll never run into anything on the Pi where the speed of lazy ranges versus ranges is a problem, or even a concern, but it's part of what helps make Python 3 faster and the lazy way is generally considered to be the right way amidst the programming neckbeards.

## Ranges for fun and profit

So now you know exactly what a range is for, what can we do with it that matters to you? Let's practice some multiplication tables:

``````>>> def multiplication_table(table, results):
...     list(range(0,(table*results)-1,table))
...
>>> multiplication_table(3, 5)
[0, 3, 6, 9, 12]
>>> multiplication_table(7, 5)
[0, 7, 14, 21, 28]
``````

Superb. We've now got a Python one liner for generating ranges we can practise with. Can we make it more useful?

``````def multiplication_table(number, number_of_items):
return list(range(0, (number*(number_of_items+1)), number))[1:]
``````

Ta daa:

``````>>> multiplication_table(9, 10)
[9, 18, 27, 36, 45, 54, 63, 72, 81, 90]
``````

## Reverse my range!

If you play with ranges for a while, you might find yourself trying something like this:

``````>>> list(range(9,0))
[]
``````

Whoa? What happened there? Well the default value for the third argument of `range` is 1. If you try to count from 9 down to 0 by counting up 1 every time then you're going to have a very, very hard time getting there:

• 9
• 10 ?
• 11 ... eek!
• 12 ... this isn't going well
• ...
• 20 ... well, we've one one 0?

There's a simple fix for this:

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

This has an interesting side-effect:

• If you create a range from 0 to 9 you'll get 0, 1, 2, 3, 4, 5, 6, 7, 8.
• If you create a range from 9 to 0 you'll get 9, 8, 7, 6, 5, 4, 3, 2, 1.

You can either adjust your start/end accordingly, or optionally used the `reversed` function like so:

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

The `reversed` function will give you a reversed list, so you can count from 0 to 9 and then reverse it to get a countdown. `reversed` can also be used with lists, and isn't limited to just reversing lists of numbers.

Unless you have a really, really good reason, don't use it. Let's ask Python 3 why:

``````>>> xrange(0,10)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'xrange' is not defined
``````

In Python 3, `range` was updated to behave in the same way as `xrange` did in Python 2, rendering `xrange` obsolete. It's simply been removed.

xrange is one of those classic examples of language bloat, where things start to creep in that make sense but inevitably just complicate what's a really simple problem. In your Python adventures you're very unlikely to find an example where you're using exclusively Python 2 and need the extra performance that `xrange` can potentially offer. Stick with `range` and ensure your code will run in Python 3.

That's all folks!

Search above to find more great tutorials and guides.

# Plasma 2040

Swathe everything in rainbows with this all-in-one, USB-C powered controller for WS2812/Neopixel and APA102/Dotstar addressable LED strip.