# Lists

Steven D'Aprano steve+comp.lang.python at pearwood.info
Mon Sep 15 08:59:36 CEST 2014

```Seymore4Head wrote:

> import random
> nums=range(1,11)
> print (nums)
> samp=random.sample(nums,10)
> top=nums
> newlist=nums[::-1]
> tail=newlist
>
> for x in range(10):
>     print ("Top {:2d}    Tail {:2.0f}  Sample {:2d}
> ".format(top[x],tail[x],samp[x]))
>
> I don't understand why the command nums=range(1,11) doesn't work.

Of course it works. It does exactly what you told it to do: set the
variable "nums" to the result of calling range(1, 11). The only question
is, what does range(1, 11) do?

> I would think that print(nums) should be 1,2,3 ect.

Did you read the documentation for range?

py> help(range)
class range(object)
|  range([start,] stop[, step]) -> range object
|
|  Returns a virtual sequence of numbers from start to stop by step.
[...]

range in Python 3 does not return a list. It returns a special object which
provides a sequence of numbers, but without actually storing them all in a
list.

> Why does random.sample(nums,10) give me the numbers between 1 and 10.

What did you expect it to do? Did you read the documentation?

py> import random
py> help(random.sample)
Help on method sample in module random:

sample(self, population, k) method of random.Random instance
Chooses k unique random elements from a population sequence or set.
[...]
To choose a sample in a range of integers, use range as an argument.
This is especially fast and space efficient for sampling from a
large population:   sample(range(10000000), 60)

The docs even tell you that (1) sample supports range objects, and (2) using
range is more efficient than lists.

> I am missing something subtle again.

range objects behave *like* lists when you index them:

py> nums = range(1, 100)
py> nums[0]  # First item.
1
py> nums[-1]  # Last item.
99

They're even smart enough that you can take a slice, and they give you a new
range object:

py> nums[1:10]
range(2, 11)

When you iterate over them, you get each item in turn:

py> for i in range(1, 4):
...     print(i)
...
1
2
3

range objects are more efficient than lists if the numbers follow the right
sort of pattern. While a list can contain any values you like, in any
order:

py> nums = [1, 33, 5, 222, 4, 6, 0, 8888888, 7]

range objects are limited to a linear sequence of:

start, start+step, start+2*step, start+3*step, ...

up to some end value. The reason range is more efficient is that, unlike
lists, it doesn't need to pre-populate all the values required, it can
calculate them on the fly when and as required. The reason why lists are
more flexible is that the values don't have to be calculated as needed,
they can just be stored, ready to use.

--
Steven

```