Как лучше всего скопировать список? Я знаю следующие способы, какой из них лучше? Или есть другой способ?
lst = ['one', 2, 3]
lst1 = list(lst)
lst2 = lst[:]
import copy
lst3 = copy.copy(lst)






Если вам нужна неглубокая копия (элементы не копируются), используйте:
lst2=lst1[:]
Если вы хотите сделать глубокую копию, используйте модуль копирования:
import copy
lst2=copy.deepcopy(lst1)
Если элементы являются изменяемыми объектами, они передаются по ссылке, вы должны использовать deepcopy, чтобы действительно скопировать их.
Он будет копировать только те ссылки, которые содержатся в списке. Если элемент в списке содержит ссылку на другой объект, он не будет скопирован. В 9 случаях из 10 вам просто нужна неглубокая копия.
@sheats см. stackoverflow.com/questions/184710/…
примечание: допустили ошибку, приняв lst2 = lst1 за мелкую копию, это просто ссылка.
Более четкий подход: lst2 = list (lst1)
@ CᴴᴀZ из всех упомянутых методов, включая тот, который вы упомянули, который является лучшим, я имею в виду с точки зрения оптимизации кода ..
Я часто использую:
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() всякий раз, когда у вас есть ссылка внутри объекта.
Я подумал, что ваш трюк с использованием lst1*1 был действительно хорош ... но, к сожалению, грубое профилирование предполагает, что он как минимум в два раза медленнее, чем lst1[:], который немного быстрее, чем copy(last1).
Вы также можете сделать это:
import copy
list2 = copy.copy(list1)
Это должно делать то же самое, что и поверхностная копия Марка Родди.
Вы также можете:
a = [1, 2, 3]
b = list(a)
Результат - неглубокая или глубокая копия?
Нет, использование list () определенно является мелкой копией. Попробуйте сами.
Есть ли разница в скорости? Возможно, когда вы выполняете [:], библиотека достаточно умна, чтобы знать, что создается копия, и, следовательно, она потенциально может вызвать для этого некоторый собственный код C. С list(iterable) знает ли / заботится ли он о том, что итерируемый объект уже материализован и, следовательно, может быть эффективно скопирован?
Итак, это единственный способ получить полную копию списка с помощью модуля копирования? Кажется странным, что Python не включает глубокую копию в свои стандартные функции.
Я люблю делать:
lst2 = list(lst1)
Преимущество перед lst1 [:] в том, что та же идиома работает для dicts:
dct2 = dict(dct1)
На самом деле в списке рассылки Python 3K было довольно долгое обсуждение копии словаря и копии списка: mail.python.org/pipermail/python-3000/2008-Feb February/…
Немного информации здесь заключается в том, что для словарей вы можете сделать d = d.copy ()
С точки зрения производительности вызов 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) они примерно такие же.
Я бы не стал беспокоиться, если мне нужно сделать одну копию между сотнями строк кода. Я могу беспокоиться, только если это основная часть приложения и частое копирование списка.
Что вы имеете в виду, говоря, что элементы не копируются?