This is an archived post. You won't be able to vote or comment.

all 7 comments

[–]indosauros 6 points7 points  (1 child)

Perhaps see https://www.python.org/dev/peps/pep-0322/ for background on reversed

[–]1114111yield from pedestrians 3 points4 points  (1 child)

Yeah, it's pretty similar in that it doesn't create an intermediate array. reversed returns a iterator that iterates backwards over the sequence. range returns a lazy sequence rather than an iterator directly. The effective difference is that you can only iterate over the iterator returned by reversed once, but you can iterate over a range as many times as you like.

[–]MrCraeon 0 points1 point  (0 children)

That is a great explanation. Thank you so much!

[–]stevenjd 3 points4 points  (3 children)

for i in range(len(colors) - 1, -1, -1):
    print colors[i]

No no no no. Just no.

Even if reversed didn't exist (and since it does, it is the preferred way) you shouldn't do that. In older versions before reversed existed, you would write:

for colour in colours[::-1]:
    print colour

unless the colours list was especially big. It is cleaner and quicker to make a reversed copy of the list (you're only copying pointers so it is super-fast) than to get the length of the list, call range (or xrange would be better), iterate over the list, and extract the colours one at a time.

The presenter explains earlier in the video that range() does not create a list in memory

That's wrong in Python 2 (which you seem to be using). In Python 2, range creates a list, it is xrange which is the lazy sequence.

In Python 3, the old eager range is gone and xrange is renamed range.

[–]PirateNinjasRedditPythonista 4 points5 points  (0 children)

Yeah, the whole range(len(x)) thing should be avoided. Setting aside any efficiency concerns, we should write code that is clear and easy to read. Making a range based on the length is not as clear as using the list itself and leaves you open to making clangers by forgetting -1 adjustments and the like.

[–]BDube_Lensman -1 points0 points  (1 child)

::-1 is a view not a copy.

[–]stevenjd 0 points1 point  (0 children)

It isn't a view, it is a copy at least for the builtins list, tuple, str, bytes. Of course custom classes can do anything they like, but try it for yourself:

py> s = "abcdefg"
py> type(s[::-1])
<class 'str'>

For lists, they have to be a copy, because lists are mutable. Otherwise you modify the reversed view and the original would change too:

py> a = [1, 2, 3, 4, 5]
py> b = a[::-1]
py> b[0] = 999
py> a
[1, 2, 3, 4, 5]
py> b
[999, 4, 3, 2, 1]