views:

180

answers:

3

In Python, what is the best way to create a new list whose items are the same as those of some other list, but in reverse order? (I don't want to modify the existing list in place.)

Here is one solution that has occurred to me:

new_list = list(reversed(old_list))

It's also possible to duplicate old_list then reverse the duplicate in place:

new_list = list(old_list) # or `new_list = old_list[:]`
new_list.reverse()

Is there a better option that I've overlooked? If not, is there a compelling reason (such as efficiency) to use one of the above approaches over the other?

+15  A: 
newlist = oldlist[::-1]

The [::-1] slicing (which my wife Anna likes to call "the Martian smiley";-) means: slice the whole sequence, with a step of -1, i.e., in reverse. It works for all sequences.

Note that this (and the alternatives you mentioned) is equivalent to a "shallow copy", i.e.: if the items are mutable and you call mutators on them, the mutations in the items held in the original list are also in the items in the reversed list, and vice versa. If you need to avoid that, a copy.deepcopy (while always a potentially costly operation), followed in this case by a .reverse, is the only good option.

Alex Martelli
Oh my! That _is_ elegant. Until a few days ago I didn't realize that it's possible to include a "step" when slicing; now I'm wondering how I ever got by without it! Thanks, Alex. :)
davidchambers
@David, you're welcome!
Alex Martelli
Thanks, too, for mentioning that this produces a shallow copy. That's all I need, though, so I'm about to add a Martian smiley to my code.
davidchambers
+1  A: 

Perhaps what you are looking for is:

new_list = [i for i in reversed(old_list)]
inspectorG4dget
`list(reversed(...))` as the OP proposes is faster, more concise, and more readable, so why would anybody use a listcomp here? The point of my A is that a martian-smiley is _even_ faster and more concise (so one had better _learn_ to read it anyway, if one finds it non-intuitive;-).
Alex Martelli
+3  A: 

Now let's timeit. Hint: Alex's [::-1] is fastest :)

$ p -m timeit "ol = [1, 2, 3]; nl = list(reversed(ol))"
100000 loops, best of 3: 2.34 usec per loop

$ p -m timeit "ol = [1, 2, 3]; nl = list(ol); nl.reverse();"
1000000 loops, best of 3: 0.686 usec per loop

$ p -m timeit "ol = [1, 2, 3]; nl = ol[::-1];"
1000000 loops, best of 3: 0.569 usec per loop

$ p -m timeit "ol = [1, 2, 3]; nl = [i for i in reversed(ol)];"
1000000 loops, best of 3: 1.48 usec per loop


$ p -m timeit "ol = [1, 2, 3]*1000; nl = list(reversed(ol))"
10000 loops, best of 3: 44.7 usec per loop

$ p -m timeit "ol = [1, 2, 3]*1000; nl = list(ol); nl.reverse();"
10000 loops, best of 3: 27.2 usec per loop

$ p -m timeit "ol = [1, 2, 3]*1000; nl = ol[::-1];"
10000 loops, best of 3: 24.3 usec per loop

$ p -m timeit "ol = [1, 2, 3]*1000; nl = [i for i in reversed(ol)];"
10000 loops, best of 3: 155 usec per loop

Update: Added list comp method suggested by inspectorG4dget. I'll let the results speak for themselves.

sdolan