创建“一个”的最佳方法;颠倒;Python中的列表?

创建“一个”的最佳方法;颠倒;Python中的列表?,python,reverse,html-lists,Python,Reverse,Html Lists,在Python中,创建一个新列表的最佳方法是什么,该列表的项目与其他列表的项目相同,但顺序相反?(我不想就地修改现有列表。) 我想到了一个解决方案: new_list = list(reversed(old_list)) 也可以复制旧的\u列表,然后在适当的位置反转副本: new_list = list(old_list) # or `new_list = old_list[:]` new_list.reverse() 有没有我忽略的更好的选择?如果没有,是否有令人信服的理由(如效率)使用上

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

我想到了一个解决方案:

new_list = list(reversed(old_list))
也可以复制
旧的\u列表
,然后在适当的位置反转副本:

new_list = list(old_list) # or `new_list = old_list[:]`
new_list.reverse()
有没有我忽略的更好的选择?如果没有,是否有令人信服的理由(如效率)使用上述方法中的一种而不是另一种

newlist = oldlist[::-1]
[::-1]
切片(我妻子安娜喜欢称之为“火星人的微笑”;-)的意思是:用-1的步骤,即相反的步骤,切片整个序列。它适用于所有序列

请注意,这(以及您提到的备选方案)相当于“浅拷贝”,即:如果项目是可变的,并且您对其调用了突变子,则原始列表中的项目中的突变也会出现在反向列表中的项目中,反之亦然。如果您需要避免这种情况,唯一好的选择是执行
复制.deepcopy
(虽然这始终是一项潜在的昂贵操作),在这种情况下,执行
.reverse
。提示:Alex的
[::-1]
最快:)

更新:添加了inspectorG4dget建议的列表补偿方法。我会让结果说明一切。

值得为sdolan的timeit计算提供一个基线基准/调整,它显示了“反向”的性能,而不需要经常不必要的
list()
转换。此
list()
操作向运行时添加额外的26个usecs,并且仅在迭代器不可接受的情况下才需要

结果:

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(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(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倍!那很优雅。直到几天前,我才意识到切片时可以包含“步骤”;现在我想知道没有它我怎么过得去!谢谢你,亚历克斯也谢谢你提到这会产生一个肤浅的副本。这就是我所需要的,所以我要在我的代码中添加一个火星人的笑脸。这看起来真的比最初的建议,
list(reversed(oldlist))
更神奇,可读性也更低。除了一个小的微优化之外,还有什么理由更喜欢
[::-1]
而不是
反向()?如果您完全理解切片,那么它完全有意义。如果您不了解切片…那么,您真的应该在Python职业生涯的早期就学习它。当然,当您不需要列表时,
reversed
具有巨大的优势,因为它不会浪费内存或前期构建时间。但是当您确实需要列表时,使用
[::-1]
而不是
列表(reversed())
类似于在我使用的代码中使用
[listcomp]
而不是
列表(genexpr)
@abarnert,我很少看到第三个slice参数,如果我看到它的用法,我必须查找它的含义。一旦我这样做了,当步骤为负时,默认的开始值和结束值是否交换仍然不明显。快速看一眼,在不查找第三个参数的含义的情况下,我可能会猜测
[::-1]
意味着删除列表的最后一个元素,而不是将其反转<代码>反向(列表)
精确地说明它在做什么;它从“显式优于隐式”、“可读性计数”和“稀疏优于稠密”的意义上阐明了它的意图。reversed()返回一个迭代对象,该对象是惰性计算的,因此我认为它与切片符号[:-1]一般来说是不公平的。即使在可以直接使用迭代器的情况下,例如
''.join(反向(['1','2','3'])
,切片方法仍然快了30%以上。难怪前两个测试的结果相同:它们完全相同!我的结果与此更为相似。ol[::-1]的时间大约是list(reversed(ol))的两倍。ol[::-1]方法写入字符数更少。然而,列表(reversed(ol))对于python初学者来说可能更具可读性,而且在我的机器上速度更快。请注意,这对于创建反向复制列表是准确的,但是对于迭代来说反向复制比反向复制更有效。
[::-1]