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

105 投票
3 回答
90468 浏览
提问于 2025-04-16 04:06

在Python中,如何创建一个新列表,这个新列表的内容和另一个列表的内容一样,但顺序是反过来的?(我不想直接改动原来的列表。)

这里有一个我想到的解决办法:

new_list = list(reversed(old_list))

还可以先复制一份old_list,然后把复制的列表反转:

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

有没有更好的方法我没想到?如果没有的话,以上这些方法中,有没有哪个在效率上更好一些?

3 个回答

11

调整

这里值得提一下,sdolan 提供的 timeit 计算结果中,给出了一个基准参考,展示了 'reversed' 的性能,而没有使用通常不必要的 list() 转换。这个 list() 操作会额外增加 26 微秒的运行时间,只有在迭代器不合适的情况下才需要使用。

结果:

reversed(lst) -- 11.2 usecs

list(reversed(lst)) -- 37.1 usecs

lst[::-1] -- 23.6 usecs

计算:

# 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

结论:

这些测试的结论是,reversed() 比切片 [::-1] 快 12.4 微秒。

65

现在我们来看看timeit这个工具。提示:Alex 提到的 [::-1] 是最快的哦 :)

$ 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

更新:添加了 inspectorG4dget 提出的列表推导方法。我会让结果自己说话。

232
newlist = oldlist[::-1]

这个 [::-1] 切片(我妻子安娜喜欢叫它“火星人微笑”;-))的意思是:把整个序列反向切片,也就是从后往前切。这个方法适用于所有类型的序列。

需要注意的是,这个方法(以及你提到的其他方法)是等同于“浅拷贝”的,也就是说:如果里面的元素是可变的(可以改变的),当你对它们进行修改时,原始列表中的元素和反转后的列表中的元素会同时发生变化,反之亦然。如果你想避免这种情况,使用 copy.deepcopy(虽然这个操作可能会比较耗费资源),然后再用 .reverse,这是唯一好的选择。

撰写回答