使用 new_list = my_list
时,对 new_list
的任何修改每次都会更改 my_list
。为什么会这样,我如何克隆或复制列表以防止它?
原文由 aF. 发布,翻译遵循 CC BY-SA 4.0 许可协议
Felix 已经提供了一个很好的答案,但我想我会对各种方法进行速度比较:
copy.deepcopy(old_list)
Copy()
使用 deepcopy 复制类的方法Copy()
方法不复制类(仅字典/列表/元组)for item in old_list: new_list.append(item)
[i for i in old_list]
( 列表理解)copy.copy(old_list)
list(old_list)
new_list = []; new_list.extend(old_list)
old_list[:]
( 列表切片)所以最快的是列表切片。 But be aware that copy.copy()
, list[:]
and list(list)
, unlike copy.deepcopy()
and the python version don’t copy any lists, dictionaries and class列表中的实例,因此如果原件发生变化,它们也会在复制的列表中发生变化,反之亦然。
(如果有人感兴趣或想提出任何问题,这里是脚本:)
from copy import deepcopy
class old_class:
def __init__(self):
self.blah = 'blah'
class new_class(object):
def __init__(self):
self.blah = 'blah'
dignore = {str: None, unicode: None, int: None, type(None): None}
def Copy(obj, use_deepcopy=True):
t = type(obj)
if t in (list, tuple):
if t == tuple:
# Convert to a list if a tuple to
# allow assigning to when copying
is_tuple = True
obj = list(obj)
else:
# Otherwise just do a quick slice copy
obj = obj[:]
is_tuple = False
# Copy each item recursively
for x in xrange(len(obj)):
if type(obj[x]) in dignore:
continue
obj[x] = Copy(obj[x], use_deepcopy)
if is_tuple:
# Convert back into a tuple again
obj = tuple(obj)
elif t == dict:
# Use the fast shallow dict copy() method and copy any
# values which aren't immutable (like lists, dicts etc)
obj = obj.copy()
for k in obj:
if type(obj[k]) in dignore:
continue
obj[k] = Copy(obj[k], use_deepcopy)
elif t in dignore:
# Numeric or string/unicode?
# It's immutable, so ignore it!
pass
elif use_deepcopy:
obj = deepcopy(obj)
return obj
if __name__ == '__main__':
import copy
from time import time
num_times = 100000
L = [None, 'blah', 1, 543.4532,
['foo'], ('bar',), {'blah': 'blah'},
old_class(), new_class()]
t = time()
for i in xrange(num_times):
Copy(L)
print 'Custom Copy:', time()-t
t = time()
for i in xrange(num_times):
Copy(L, use_deepcopy=False)
print 'Custom Copy Only Copying Lists/Tuples/Dicts (no classes):', time()-t
t = time()
for i in xrange(num_times):
copy.copy(L)
print 'copy.copy:', time()-t
t = time()
for i in xrange(num_times):
copy.deepcopy(L)
print 'copy.deepcopy:', time()-t
t = time()
for i in xrange(num_times):
L[:]
print 'list slicing [:]:', time()-t
t = time()
for i in xrange(num_times):
list(L)
print 'list(L):', time()-t
t = time()
for i in xrange(num_times):
[i for i in L]
print 'list expression(L):', time()-t
t = time()
for i in xrange(num_times):
a = []
a.extend(L)
print 'list extend:', time()-t
t = time()
for i in xrange(num_times):
a = []
for y in L:
a.append(y)
print 'list append:', time()-t
t = time()
for i in xrange(num_times):
a = []
a.extend(i for i in L)
print 'generator expression extend:', time()-t
原文由 cryo 发布,翻译遵循 CC BY-SA 4.0 许可协议
4 回答4.5k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
4 回答3.8k 阅读✓ 已解决
3 回答2.2k 阅读✓ 已解决
1 回答4.4k 阅读✓ 已解决
1 回答3.9k 阅读✓ 已解决
1 回答2.8k 阅读✓ 已解决
new_list = my_list
实际上并没有创建第二个列表。分配只是复制对列表的引用,而不是实际列表,因此new_list
和my_list
在分配后引用相同的列表。要实际复制列表,您有几个选项:
list.copy()
方法(自 Python 3.3 起可用):Alex Martelli 对此的看法(至少 早在 2007 年)是, _它是一种怪异的语法,永远使用它没有意义_。 ;)(在他看来,下一个更具可读性)。
list()
构造函数:copy.copy()
:这比
list()
慢一点,因为它必须首先找出old_list
的数据类型。copy.deepcopy()
:显然是最慢和最需要内存的方法,但有时是不可避免的。这是递归操作的;它将处理任意数量的嵌套列表(或其他容器)级别。
例子:
结果: