Как лучше всего скопировать список?

Как лучше всего скопировать список? Я знаю следующие способы, какой из них лучше? Или есть другой способ?

lst = ['one', 2, 3]

lst1 = list(lst)

lst2 = lst[:]

import copy
lst3 = copy.copy(lst)
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
59
0
66 682
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Ответ принят как подходящий

Если вам нужна неглубокая копия (элементы не копируются), используйте:

lst2=lst1[:]

Если вы хотите сделать глубокую копию, используйте модуль копирования:

import copy
lst2=copy.deepcopy(lst1)

Что вы имеете в виду, говоря, что элементы не копируются?

sheats 09.10.2008 00:16

Если элементы являются изменяемыми объектами, они передаются по ссылке, вы должны использовать deepcopy, чтобы действительно скопировать их.

Andrea Ambu 09.10.2008 00:20

Он будет копировать только те ссылки, которые содержатся в списке. Если элемент в списке содержит ссылку на другой объект, он не будет скопирован. В 9 случаях из 10 вам просто нужна неглубокая копия.

Jason Baker 09.10.2008 00:22

@sheats см. stackoverflow.com/questions/184710/…

David Locke 09.10.2008 01:08

примечание: допустили ошибку, приняв lst2 = lst1 за мелкую копию, это просто ссылка.

Aram Kocharyan 29.09.2012 17:40

Более четкий подход: lst2 = list (lst1)

CᴴᴀZ 15.05.2016 18:29

@ CᴴᴀZ из всех упомянутых методов, включая тот, который вы упомянули, который является лучшим, я имею в виду с точки зрения оптимизации кода ..

Eswar 18.09.2018 11:07

Я часто использую:

lst2 = lst1 * 1

Если lst1 содержит другие контейнеры (например, другие списки), вы должны использовать deepcopy из библиотеки копирования, как показано Марком.


ОБНОВЛЕНИЕ: объяснение deepcopy

>>> a = range(5)
>>> b = a*1
>>> a,b
([0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
>>> a[2] = 55 
>>> a,b
([0, 1, 55, 3, 4], [0, 1, 2, 3, 4])

Как видите, изменилось только ... Попробую сейчас со списком списков

>>> 
>>> a = [range(i,i+3) for i in range(3)]
>>> a
[[0, 1, 2], [1, 2, 3], [2, 3, 4]]
>>> b = a*1
>>> a,b
([[0, 1, 2], [1, 2, 3], [2, 3, 4]], [[0, 1, 2], [1, 2, 3], [2, 3, 4]])

Не очень читабельно, позвольте мне распечатать его с помощью for:

>>> for i in (a,b): print i   
[[0, 1, 2], [1, 2, 3], [2, 3, 4]]
[[0, 1, 2], [1, 2, 3], [2, 3, 4]]
>>> a[1].append('appended')
>>> for i in (a,b): print i

[[0, 1, 2], [1, 2, 3, 'appended'], [2, 3, 4]]
[[0, 1, 2], [1, 2, 3, 'appended'], [2, 3, 4]]

Ты видишь это? Он также добавлен к b [1], поэтому b [1] и a [1] - это один и тот же объект. Теперь попробуйте с deepcopy

>>> from copy import deepcopy
>>> b = deepcopy(a)
>>> a[0].append('again...')
>>> for i in (a,b): print i

[[0, 1, 2, 'again...'], [1, 2, 3, 'appended'], [2, 3, 4]]
[[0, 1, 2], [1, 2, 3, 'appended'], [2, 3, 4]]

copy() не будет работать в последнем случае, вам понадобится deepcopy() всякий раз, когда у вас есть ссылка внутри объекта.

Aram Kocharyan 29.09.2012 17:26

Я подумал, что ваш трюк с использованием lst1*1 был действительно хорош ... но, к сожалению, грубое профилирование предполагает, что он как минимум в два раза медленнее, чем lst1[:], который немного быстрее, чем copy(last1).

Andrew 12.07.2016 23:21

Вы также можете сделать это:

import copy
list2 = copy.copy(list1)

Это должно делать то же самое, что и поверхностная копия Марка Родди.

Вы также можете:

a = [1, 2, 3]
b = list(a)

Результат - неглубокая или глубокая копия?

minty 09.10.2008 22:49

Нет, использование list () определенно является мелкой копией. Попробуйте сами.

Christian Oudard 02.09.2009 17:03

Есть ли разница в скорости? Возможно, когда вы выполняете [:], библиотека достаточно умна, чтобы знать, что создается копия, и, следовательно, она потенциально может вызвать для этого некоторый собственный код C. С list(iterable) знает ли / заботится ли он о том, что итерируемый объект уже материализован и, следовательно, может быть эффективно скопирован?

Hamish Grubijan 09.11.2012 02:27

Итак, это единственный способ получить полную копию списка с помощью модуля копирования? Кажется странным, что Python не включает глубокую копию в свои стандартные функции.

Shuklaswag 13.01.2018 18:57

Я люблю делать:

lst2 = list(lst1)

Преимущество перед lst1 [:] в том, что та же идиома работает для dicts:

dct2 = dict(dct1)

На самом деле в списке рассылки Python 3K было довольно долгое обсуждение копии словаря и копии списка: mail.python.org/pipermail/python-3000/2008-Feb February/…

Mark Roddy 09.10.2008 20:31

Немного информации здесь заключается в том, что для словарей вы можете сделать d = d.copy ()

Christian Oudard 02.09.2009 17:04

С точки зрения производительности вызов list() сопряжен с некоторыми накладными расходами по сравнению с нарезкой. Итак, для коротких списков lst2 = lst1[:] примерно в два раза быстрее, чем lst2 = list(lst1).

В большинстве случаев это, вероятно, перевешивается тем фактом, что list() более читабелен, но в жестких циклах это может быть ценной оптимизацией.

Короткие списки, [:] - лучшее:

In [1]: l = range(10)

In [2]: %timeit list(l)
1000000 loops, best of 3: 477 ns per loop

In [3]: %timeit l[:]
1000000 loops, best of 3: 236 ns per loop

In [6]: %timeit copy(l)
1000000 loops, best of 3: 1.43 us per loop

Для больших списков все примерно одинаково:

In [7]: l = range(50000)

In [8]: %timeit list(l)
1000 loops, best of 3: 261 us per loop

In [9]: %timeit l[:]
1000 loops, best of 3: 261 us per loop

In [10]: %timeit copy(l)
1000 loops, best of 3: 248 us per loop

Для очень больших списков (я пробовал 50MM) они примерно такие же.

Я бы не стал беспокоиться, если мне нужно сделать одну копию между сотнями строк кода. Я могу беспокоиться, только если это основная часть приложения и частое копирование списка.

Saurabh 11.06.2013 10:13

Другие вопросы по теме