List slicing (ommitting) with python 3.What has changed?

python

#1



I have been pracising list slicing using the range() with python 3 but wheneve I type list=[start:end:stride] python 3 won't print the list as expected.

I expect it to print the list of values according to instructions given by list slicing code.For instance in the code below I expect it to print a list of [,9,7,5,3] but instead it brings "[range(1,11)]". Why is this so with python 3 yet with python 2 it works perfectly

my_list = [range(1, 11)]
backwards=my_list[::-2]
print (backwards)


#2

Hi @dephysics9 ,

Python 3 has a range type that you will need to convert to a list. See below ...

my_list = range(1, 11) # create a range
backwards_sequence = my_list[::-2] # reverse the range and skip alternate items
print(type(backwards_sequence)) # show us that it is a range and not yet a list
backwards = list(backwards_sequence) # convert the range to a list
print(type(backwards)) # now we have a list
print(backwards)

Output ...

<class 'range'>
<class 'list'>
[10, 8, 6, 4, 2]

#3

Thank you so much for your help.I had no idea about changing range to list first.Thanks


#4

EDIT (June 16, 2016) - The following applies to Python 3.x. For Python 2.x, you may be interested in looking at xrange.

Hello again @dephysics9 ,

Note that in your original code you have this ...

my_list = [range(1, 11)]

That creates a range inside a list. If you do this instead ...

my_list = range(1, 11)
backwards = my_list[::-2]
print(backwards)

... you will see this output ...

range(10, 0, -2)

... and that is perhaps the most beautiful part of this story. The Python community is very clever, and is always coming up with new ways to improve the Python language. To store a list of 1000000000 items, you store all 1000000000 items. But to store a range of any number of items, the only information you need to store is the start, end, and stride values.

For a range that might include a billion values, that is a great advantage over a list.

my_range = range(1000000020, 20, -1)
print(my_range)

Output ...

range(1000000020, 20, -1)

We only needed to store three values instead of a billion of them.


#5

Actually I was getting range(10,0,-2) as the output .What does it mean. How do you intepret it?


#6

First, you create a range that includes all the integers from 1 to 10, inclusive. Since 11 was the end value, it was not included.

my_list = range(1, 11)

Then you reverse the order of the integers, and skip every other one, with your stride being -2.

backwards=my_list[::-2]

Now, with the order reversed, 0 is the exclusive end value, so that the range stops without including 0. The result is a range that begins at 10 and descends with stride of -2 to an end value of 0. So you get this ...

range(10, 0, -2)


#7

Well that explains it clearly but if by reversing the integers means that zero is excluded how comes it is being printed in range(10,0,-2) instead of range(10,1,-2)


#8

Excellent; that is a type of question that all programmers should consider, because it is essential to consider details while programming.

The Python 3.x documentation on range is here:
class range(stop); class range(start, stop[, step]).

We'll use the same terminology here as the documentation does. Note that they use start, stop, and step.

For clarity, here's a new version of the code we have been discussing ...

# Using Python 3.x on IDLE
# June 17, 2016
ascending_range = range(1, 11) # create ascending range
print(ascending_range) # print ascending range
ascending_list = list(ascending_range) # convert to ascending list
print(ascending_list) # print ascending list
backwards_range = ascending_range[::-2] # reverse range; step -2
print(backwards_range) # print backwards range
backwards_list = list(backwards_range) # convert to backwards list
print(backwards_list) # print backwards list

Output ,,,

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

Basically, the reason why the stop value of the reversed range is 0 rather than 1 is that when we defined the original range, we used a start value of 1, which is inclusive. When we reverse the range, the system uses the original start value to compute the new stop value. Since the stop value is exclusive, the system goes past the start value by 1 when computing the new stop value to guarantee that the original start value will be included in the new range, if the step value allows it. Because we are now using a negative step, going past the start value by 1 means subtracting 1 from the original start value to get the new stop value. The absolute value of the step does not matter when computing the new stop value; rather it is the sign of the step that matters, which is negative in this case.

Although a stop value of either 0 or 1 would have given us the same output, the most elegant policy is for the system to simply go 1 past the original start value to create the new stop value. It will always include the correct values in the new range.


#9

This is excellent! I understand it perfectly well now.Thank you for explaining in details.