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

dav*_*ers 85 python reverse html-lists

在Python中,创建新列表的最佳方法是什么,其列表的项目与其他列表的项目相同,但顺序相反?(我不想修改现有的列表.)

这是我遇到的一个解决方案:

new_list = list(reversed(old_list))
Run Code Online (Sandbox Code Playgroud)

也可以复制old_list然后反复复制到位:

new_list = list(old_list) # or `new_list = old_list[:]`
new_list.reverse()
Run Code Online (Sandbox Code Playgroud)

有没有更好的选择我忽略了?如果没有,是否有令人信服的理由(如效率)使用上述方法之一而不是另一种?

Ale*_*lli 198

newlist = oldlist[::-1]
Run Code Online (Sandbox Code Playgroud)

[::-1]切片(其中我的妻子安娜喜欢称之为"火星笑脸" ;-)表示:切片的整个序列,为-1的步骤,即逆转.它适用于所有序列.

请注意,这(以及您提到的替代方案)等同于"浅层副本",即:如果项目是可变的并且您在其上调用mutator,则原始列表中保留的项目中的突变也位于反转清单,反之亦然.如果你需要避免这种情况,那么a copy.deepcopy(虽然总是一个可能很昂贵的操作),在这种情况下是a .reverse,后面是唯一的好选择.

  • 这真的看起来比原来的建议更有魔力和可读性,`list(reverse(oldlist))`.除了微小的优化之外,有没有理由更喜欢`[:: - 1]`到`reversed()`? (13认同)
  • @abarnert在我使用的代码中,我很少看到第三个切片参数,如果我看到它的使用,我必须查看它的含义.一旦我这样做,当步骤为负时,交换默认的开始和结束值仍然不明显.快速浏览,没有查找第三个参数的含义,我可能会猜测`[:: - 1]`意味着删除列表的最后一个元素,而不是反转它.`反向(列表)`说明它正在做什么; 它明确了它的意图,意思是"明确比隐含更好","可读性计数","稀疏优于密集". (10认同)
  • +1用于添加妻子对解决方案的贡献. (3认同)
  • @BrianCampbell:它有什么“魔力”?如果您完全了解切片,那就完全有道理了。如果您不了解切片……那么,您确实应该在 Python 职业生涯的早期就学习它。当然,当您不需要列表时,“反向”具有巨大的优势,因为它不会浪费内存或预先构建列表的时间。但是,当您确实需要列表时,使用“[::-1]”而不是“list(reversed())”类似于使用“[listcomp]”而不是“list(genexpr)”。 (2认同)

Sam*_*lan 54

现在让我们来吧timeit.提示:亚历克斯[::-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
Run Code Online (Sandbox Code Playgroud)

更新:添加了由inspectorG4dget建议的列表comp方法.我会让结果说明一切.

  • 只是一个注释 - 这对于创建反向复制列表是准确的,但是对于迭代然后`[:: - 1]`仍然更有效 (7认同)

mek*_*les 7

调整

值得为sdolan的时间计算提供基线基准/调整,显示"逆转"的性能,而不需要经常不必要的list()转换.此list()操作将额外的26个usecs添加到运行时,仅在迭代器不可接受的情况下才需要.

结果:

reversed(lst) -- 11.2 usecs

list(reversed(lst)) -- 37.1 usecs

lst[::-1] -- 23.6 usecs
Run Code Online (Sandbox Code Playgroud)

计算:

# 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
Run Code Online (Sandbox Code Playgroud)

结论:

这些测试的结论reversed()比切片快[::-1]12.4 usecs

  • reversed()返回一个延迟评估的迭代器对象,所以我认为它与切片符号[:: - 1]的通用性并不公平. (13认同)