在 Python 中创建“反向”列表的最佳方法是什么?

在 Python 中,如果一个新列表的项目与其他列表的项目相同,但是顺序相反,那么创建这个新列表的最佳方法是什么?(我不想在适当的位置修改现有的列表。)

我想到了一个解决办法:

new_list = list(reversed(old_list))

也有可能复制 old_list,然后将复制的内容反转到适当的位置:

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

还有更好的选择吗?如果没有,是否有令人信服的理由(比如效率)使用上述方法中的一种而不是另一种?

85764 次浏览
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.

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.

Adjustments

It's worth providing a baseline benchmark/adjustment for the timeit calculations by sdolan which show the performance of 'reversed' without the often unnecessary list() conversion. This list() operation adds an additional 26 usecs to the runtime and is only needed in the event an iterator is unacceptable.

Results:

reversed(lst) -- 11.2 usecs


list(reversed(lst)) -- 37.1 usecs


lst[::-1] -- 23.6 usecs

Calculations:

# I ran this set of 100000 and came up with 11.2, twice:
python -m timeit "ol = [1, 2, 3]*1000; nl = reversed(ol)"
100000 loops, best of 3: 11.2 usec per loop


# This shows the overhead of list()
python -m timeit "ol = [1, 2, 3]*1000; nl = list(reversed(ol))"
10000 loops, best of 3: 37.1 usec per loop


# This is the result for reverse via -1 step slices
python -m timeit "ol = [1, 2, 3]*1000;nl = ol[::-1]"
10000 loops, best of 3: 23.6 usec per loop

Conclusions:

The conclusion of these tests is reversed() is faster than the slice [::-1] by 12.4 usecs