Лучший способ создать "перевернутый" список в Python?

В Python лучший способ создать новый список, элементы которого такие же, как у другого списка, но в обратном порядке? (Я не хочу изменять существующий список на месте.)

Вот одно из решений, которое произошло со мной:

new_list = list(reversed(old_list))

Можно также дублировать old_list, а затем отменить дубликат:

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

Есть ли лучший вариант, который я забыл? Если нет, есть ли веская причина (например, эффективность) использовать один из вышеуказанных подходов над другим?

Ответ 1

newlist = oldlist[::-1]

Нарезка [::-1] (которую моя жена Анна любит называть "марсианским смайлом";-) означает: разрезать всю последовательность с шагом -1, т.е. наоборот. Он работает для всех последовательностей.

Обратите внимание, что это (и упомянутые вами альтернативы) эквивалентно "мелкой копии", то есть: если элементы изменяемы и вы вызываете на них мутаторы, мутации в элементах, хранящихся в исходном списке, также находятся в пункты в обратном списке и наоборот. Если вам нужно избегать этого, то copy.deepcopy (хотя и всегда потенциально дорогостоящая операция), в этом случае используется .reverse, является единственным хорошим вариантом.

Ответ 2

Теперь 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

Обновление: Добавлен метод списка list, предложенный inspectorG4dget. Я дам результаты говорить сами за себя.

Ответ 3

корректировок

Стоит предоставить базовый контрольный показатель/корректировку для вычислений timeit от sdolan, которые показывают производительность "полностью измененного" без часто ненужного преобразования 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() быстрее, чем срез [::-1] на 12,4 пользователя