How can you produce the following list with range()
in Python?
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
The requirement in this question calls for a list
of integers of size 10 in descending
order. So, let's produce a list in python.
# This meets the requirement.
# But it is a bit harder to wrap one's head around this. right?
>>> range(10-1, -1, -1)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
# let's find something that is a bit more self-explanatory. Sounds good?
# ----------------------------------------------------
# This returns a list in ascending order.
# Opposite of what the requirement called for.
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# This returns an iterator in descending order.
# Doesn't meet the requirement as it is not a list.
>>> reversed(range(10))
<listreverseiterator object at 0x10e14e090>
# This returns a list in descending order and meets the requirement
>>> list(reversed(range(10)))
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
because range(n)
produces an iterable there are all sorts of nice things you can do which will produce the result you desire, such as:
range(n)[::-1]
if loops are ok, we can make sort of a queue:
a = []
for i in range(n):
a.insert(0,a)
return a
or maybe use the reverse() method on it:
reverse(range(n))
Suppose you have a list call it a={1,2,3,4,5} Now if you want to print the list in reverse then simply use the following code.
a.reverse
for i in a:
print(i)
I know you asked using range but its already answered.
I thought that many (as myself) could be more interested in a common case of traversing an existing list in reversed order instead, as it's stated in the title, rather than just generating indices for such traversal.
Even though, all the right answers are still perfectly fine for this case, I want to point out that the performance comparison done in Wolf's answer is for generating indices only. So I've made similar benchmark for traversing an existing list in reversed order.
TL;DR a[::-1]
is the fastest.
Prerequisites:
a = list(range(10))
Jason's answer:
%timeit [a[9-i] for i in range(10)]
1.27 µs ± 61.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
martineau's answer:
%timeit a[::-1]
135 ns ± 4.07 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
Michał Šrajer's answer:
%timeit list(reversed(a))
374 ns ± 9.87 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
bene's answer:
%timeit [a[i] for i in range(9, -1, -1)]
1.09 µs ± 11.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
As you see, in this case there's no need to explicitly generate indices, so the fastest method is the one that makes less extra actions.
NB: I tested in JupyterLab which has handy "magic command" %timeit
. It uses standard timeit.timeit
under the hood. Tested for Python 3.7.3
range(9,-1,-1)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Very often asked question is whether range(9, -1, -1)
better than reversed(range(10))
in Python 3? People who have worked in other languages with iterators immediately tend to think that reversed() must cache all values and then return in reverse order. Thing is that Python's reversed()
operator doesn't work if the object is just an iterator. The object must have one of below two for reversed() to work:
len()
and integer indexes via []
__reversed__()
method implemented.If you try to use reversed() on object that has none of above then you will get:
>>> [reversed((x for x in range(10)))]
TypeError: 'generator' object is not reversible
So in short, Python's reversed()
is only meant on array like objects and so it should have same performance as forward iteration.
But what about range()
? Isn't that a generator? In Python 3 it is generator but wrapped in a class that implements both of above. So range(100000)
doesn't take up lot of memory but it still supports efficient indexing and reversing.
So in summary, you can use reversed(range(10))
without any hit on performance.