提问



在Python中克隆或复制列表有哪些选项?


使用new_list = my_list然后每次my_list改变时修改new_list
为什么是这样?

最佳参考


使用new_list = my_list,你实际上没有两个列表。赋值仅复制对列表的引用,而不是实际列表,因此new_listmy_list引用后的相同列表分配。


要实际复制列表,您有各种可能性:



  • 您可以使用内置list.copy()方法(自python 3.3起可用):[162]


    new_list = old_list.copy()
    

  • 您可以将其切片:


    new_list = old_list[:]
    


    Alex Martelli对此的看法(至少在2007年)是这样的,它是一种奇怪的语法,并且使用它没有任何意义。;)(在他看来,下一个更具可读性。[163] [164]

  • 您可以使用内置list()功能:[165]


    new_list = list(old_list)
    

  • 您可以使用通用copy.copy():[166]


    import copy
    new_list = copy.copy(old_list)
    


    这比list()慢一点,因为它必须首先找出old_list的数据类型。

  • 如果列表包含对象并且您想要复制它们,请使用泛型copy.deepcopy():[167]


    import copy
    new_list = copy.deepcopy(old_list)
    


    显然是最慢和最需要内存的方法,但有时是不可避免的。



示例:


import copy

class Foo(object):
    def __init__(self, val):
         self.val = val

    def __repr__(self):
        return str(self.val)

foo = Foo(1)

a = ['foo', foo]
b = a.copy()
c = a[:]
d = list(a)
e = copy.copy(a)
f = copy.deepcopy(a)

# edit orignal list and instance 
a.append('baz')
foo.val = 5

print('original: %r\n list.copy(): %r\n slice: %r\n list(): %r\n copy: %r\n deepcopy: %r'
      % (a, b, c, d, e, f))


结果:


original: ['foo', 5, 'baz']
list.copy(): ['foo', 5]
slice: ['foo', 5]
list(): ['foo', 5]
copy: ['foo', 5]
deepcopy: ['foo', 1]

其它参考1


菲利克斯已经提供了一个很好的答案,但我想我会对各种方法进行速度比较:



  1. 10.59秒(105.9us/itn) - copy.deepcopy(old_list)

  2. 10.16秒(101.6us/itn) - 使用深度复制复制类的纯python Copy()方法

  3. 1.488秒(14.88us/itn) - 纯python Copy()方法不复制类(只有dicts/lists/tuples)

  4. 0.325秒(3.25us/itn) - for item in old_list: new_list.append(item)

  5. 0.217秒(2.17us/itn) - [i for i in old_list](列表理解)

  6. 0.186秒(1.86us/itn) - copy.copy(old_list)

  7. 0.075秒(0.75us/itn) - list(old_list)

  8. 0.053秒(0.53us/itn) - new_list = []; new_list.extend(old_list)

  9. 0.039秒(0.39us/itn) - old_list[:](列表切片)



所以最快的是列表切片。但要注意copy.copy()list[:]list(list),与copy.deepcopy()不同,python版本不要复制列表中的任何列表,字典和类实例,所以如果原件发生变化,它们也会在复制的列表中发生变化,反之亦然。[168] [169] [170] [171]


(如果有人有兴趣或想提出任何问题,这里是脚本:)


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


编辑:在基准测试中添加了新式的旧式类和dicts,并使python版本更快,并添加了更多方法,包括列表表达式和extend()

其它参考2


我被告知Python 3.3+添加了list.copy()方法,它应该与切片一样快:[172] [173]


newlist = old_list.copy()

其它参考3



  

在Python中克隆或复制列表有哪些选项?




在Python 3中,可以使用以下方式创建浅表副本:


a_copy = a_list.copy()


在Python 2和3中,您可以获得一个带有原始片段的浅拷贝:


a_copy = a_list[:]


说明



有两种语义方法可以复制列表。浅拷贝创建相同对象的新列表,深拷贝创建包含新等效对象的新列表。


浅名单副本



浅拷贝仅复制列表本身,列表本身是对列表中对象的引用的容器。如果包含的对象本身是可变的并且其中一个被更改,则更改将反映在两个列表中。


在Python 2和3中有不同的方法可以做到这一点.Python 2方法也适用于Python 3。


Python 2



在Python 2中,制作列表的浅表副本的惯用方法是使用原始的完整片段:


a_copy = a_list[:]


你也可以通过列表构造函数传递列表来完成同样的事情,


a_copy = list(a_list)


但使用构造函数效率较低:


>>> timeit
>>> l = range(20)
>>> min(timeit.repeat(lambda: l[:]))
0.30504298210144043
>>> min(timeit.repeat(lambda: list(l)))
0.40698814392089844


Python 3



在Python 3中,列表得到list.copy方法:


a_copy = a_list.copy()


在Python 3.5中:


>>> import timeit
>>> l = list(range(20))
>>> min(timeit.repeat(lambda: l[:]))
0.38448613602668047
>>> min(timeit.repeat(lambda: list(l)))
0.6309100328944623
>>> min(timeit.repeat(lambda: l.copy()))
0.38122922903858125


制作另一个指针不制作副本




  使用new_list=my_list,每次my_list更改时修改new_list。这是为什么?



my_list只是一个指向内存中实际列表的名称。当你说new_list = my_list你没有复制时,你只需添加另一个指向内存中原始列表的名称。当我们制作列表副本时,我们可能会遇到类似的问题。


>>> l = [**], [], [**]
>>> l_copy = l[:]
>>> l_copy
[**], [], [**]
>>> l_copy[0].append('foo')
>>> l_copy
[**'foo'], [], [**]
>>> l
[**'foo'], [], [**]


该列表只是指向内容的指针数组,因此浅复制只复制指针,因此您有两个不同的列表,但它们具有相同的内容。要制作内容的副本,您需要一份深层副本。


深层拷贝



要在Python 2或3中制作列表的深层副本,请在copy模块中使用deepcopy:[174]


import copy
a_deep_copy = copy.deepcopy(a_list)


为了演示这如何允许我们创建新的子列表:


>>> import copy
>>> l
[**'foo'], [], [**]
>>> l_deep_copy = copy.deepcopy(l)
>>> l_deep_copy[0].pop()
'foo'
>>> l_deep_copy
[**], [], [**]
>>> l
[**'foo'], [], [**]


因此,我们看到深层复制列表与原始列表完全不同。你可以推出自己的功能 - 但是不要。你可能会通过使用标准库的深度复制功能来创建你不会有的错误。


不要使用eval



您可能会将此视为深度复制的一种方式,但不要这样做:


problematic_deep_copy = eval(repr(a_list))



  1. 这很危险,特别是如果你从一个你不信任的来源评估某些东西。

  2. 如果您复制的子元素没有表示可以重现等效元素的表示,那就不可靠了。

  3. 性能也不太好。



在64位Python 2.7中:


>>> import timeit
>>> import copy
>>> l = range(10)
>>> min(timeit.repeat(lambda: copy.deepcopy(l)))
27.55826997756958
>>> min(timeit.repeat(lambda: eval(repr(l))))
29.04534101486206


在64位Python 3.5上:


>>> import timeit
>>> import copy
>>> l = list(range(10))
>>> min(timeit.repeat(lambda: copy.deepcopy(l)))
16.84255409205798
>>> min(timeit.repeat(lambda: eval(repr(l))))
34.813894678023644

其它参考4


已经有许多答案告诉你如何制作一个正确的副本,但没有人说你原来的副本失败的原因。


Python不会将值存储在变量中;它会将名称绑定到对象。您的原始赋值也会使用my_list引用的对象并将其绑定到new_list。无论您使用哪个名称,它仍然存在只有一个列表,因此当将它称为my_list时所做的更改将在将其称为new_list时保持不变。此问题的其他每个答案都会为您提供创建要绑定到的新对象的不同方法new_list


列表的每个元素都像一个名称,因为每个元素都非唯一地绑定到一个对象。浅拷贝创建一个新列表,其元素绑定到与以前相同的对象。


new_list = list(my_list)  # or my_list[:], but I prefer this syntax
# is simply a shorter way of:
new_list = [element for element in my_list]


要使列表副本更进一步,请复制列表引用的每个对象,并将这些元素副本绑定到新列表。


import copy  
# each element must have __copy__ defined for this...
new_list = [copy.copy(element) for element in my_list]


这还不是一个深层副本,因为列表的每个元素都可以引用其他对象,就像列表绑定到它的元素一样。以递归方式复制列表中的每个元素,然后复制每个元素引用的每个其他对象,依此类推:执行深层复制。


import copy
# each element must have __deepcopy__ defined for this...
new_list = copy.deepcopy(my_list)


有关复制中的角落案例的更多信息,请参阅文档。[175]

其它参考5


new_list = list(old_list)

其它参考6


使用thing[:]


>>> a = [1,2]
>>> b = a[:]
>>> a += [3]
>>> a
[1, 2, 3]
>>> b
[1, 2]
>>> 

其它参考7


Python这样做的习惯是newList = oldList[:]

其它参考8


所有其他贡献者都提供了伟大的答案,当你有一个维度(水平)列表时,它会起作用,但是到目前为止提到的方法中只有copy.deepcopy()用于克隆/复制列表当您使用多维嵌套列表(列表列表)时,并没有指向嵌套的list对象。虽然Felix Kling在他的回答中提到了这个问题,但问题还有一点,可能还有一个使用内置函数的解决方法,这可能是deepcopy的更快替代方案。


虽然new_list = old_list[:]copy.copy(old_list)'和Py3k old_list.copy()适用于单级列表,但它们仍然指向嵌套在old_listthing[:]中的list个对象。 new_list,其中一个list对象的更改在另一个中永久存在。


编辑:揭晓新信息




  正如Aaron Hall和PM 2Ring指出的那样使用eval()不仅是一个坏主意,它也比copy.deepcopy()慢得多。

  
  这意味着对于多维列表,唯一的选择是copy.deepcopy()。话虽如此,当你尝试在中等大小的多维阵列上使用它时,它确实不是一个选择,因为性能会越来越好。我尝试timeit使用42x42阵列,而不是闻所未闻甚至是很大的生物信息学应用程序,我放弃等待响应,并开始在这篇文章中输入我的编辑。

  
  似乎唯一真正的选择是初始化多个列表并独立地处理它们。如果有人有任何其他建议,对于如何处理多维列表复制,将不胜感激。



正如其他人所说,使用copy模块和copy.deepcopy 可以 是重要的 性能问题用于多维列表 尝试在不使用deepcopy的情况下计算复制多维列表的不同方法,(我正在研究一个课程的问题,该课程只允许整个算法运行5秒才能获得学分) ,我想出了一种使用内置函数制作嵌套列表副本的方法,而不是让它们彼此指向或嵌套在它们中的list对象。我在赋值中使用eval()repr()将旧列表的副本放入新列表,而不创建旧列表的链接。它采取以下形式:


new_list = eval(repr(old_list))


基本上它的作用是将old_list表示为字符串,然后将字符串计算为字符串所代表的对象。通过这样做,没有链接到原始list对象。创建一个新的list对象,每个变量指向它自己的独立对象。以下是使用二维嵌套列表的示例。


old_list = [**0 for j in range(y)] for i in range(x)] # initialize (x,y) nested list

# assign a copy of old_list to new list without them pointing to the same list object
new_list = eval(repr(old_list)) 

# make a change to new_list 
for j in range(y):
    for i in range(x):
    new_list[i][j] += 1


如果您然后检查每个列表的内容,例如4乘3列表,Python将返回


>>> new_list

[**1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1**]

>>> old_list

[**0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0**]


虽然这可能不是规范或语法上正确的方法,但它似乎运作良好。我没有测试过性能,但我猜测eval()rep()会少一些比deepcopy运行的开销会。

其它参考9


Python 3.6.0计时



以下是使用Python 3.6.0的计时结果。请记住,这些时间是彼此相对的,而不是绝对的。


我坚持只做浅拷贝,并且还添加了一些在Python2中不可能的新方法,例如list.copy()(Python3切片等效)和列表解包(*new_list, = list):[179]]]


METHOD                  TIME TAKEN
b = a[:]                6.468942025996512   #Python2 winner
b = a.copy()            6.986593422974693   #Python3 "slice equivalent"
b = []; b.extend(a)     7.309216841997113
b = a[0:len(a)]         10.916740721993847
*b, = a                 11.046738261007704
b = list(a)             11.761539687984623
b = [i for i in a]      24.66165203397395
b = copy.copy(a)        30.853400873980718
b = []
for item in a:
  b.append(item)        48.19176080400939


考虑到Python3 list.copy()方法的可读性提高,我们可以看到老赢家仍然名列前茅,但实际上并不是很大。


请注意,这些方法不输出除列表之外的任何输入的等效结果。它们都适用于可切片对象,一些适用于任何可迭代的,但只有copy.copy()适用于任何Python对象。





以下是感兴趣方的测试代码(此处的模板):


import timeit

COUNT = 50000000
print("Array duplicating. Tests run", COUNT, "times")
setup = 'a = [0,1,2,3,4,5,6,7,8,9]; import copy'

print("b = list(a)\t\t", timeit.timeit(stmt='b = list(a)', setup=setup, number=COUNT))
print("b = copy.copy(a)\t\t", timeit.timeit(stmt='b = copy.copy(a)', setup=setup, number=COUNT))
print("b = a.copy()\t\t", timeit.timeit(stmt='b = a.copy()', setup=setup, number=COUNT))
print("b = a[:]\t\t", timeit.timeit(stmt='b = a[:]', setup=setup, number=COUNT))
print("b = a[0:len(a)]\t", timeit.timeit(stmt='b = a[0:len(a)]', setup=setup, number=COUNT))
print("*b, = a\t", timeit.timeit(stmt='*b, = a', setup=setup, number=COUNT))
print("b = []; b.extend(a)\t", timeit.timeit(stmt='b = []; b.extend(a)', setup=setup, number=COUNT))
print("b = []\nfor item in a: b.append(item)\t", timeit.timeit(stmt='b = []\nfor item in a:  b.append(item)', setup=setup, number=COUNT))
print("b = [i for i in a]\t", timeit.timeit(stmt='b = [i for i in a]', setup=setup, number=COUNT))

其它参考10


与其他具有变量和值的语言不同,Python具有名称和对象


这个说法:


a = [1,2,3]


意味着给列表(对象)一个名称a,并且:


b = a


只是给同一个对象a一个新名称b,所以每当你用a做某事时,对象就会改变,因此b会改变。


制作真正副本的唯一方法是创建新对象,就像已经说过的其他答案一样。


你可以在这里看到更多相关信息。[182]

其它参考11



  让我们从头开始,探索它有点深:



所以假设你有两个清单:


list_1=['01','98']
list_2=[**'01','98'**]


我们必须复制这两个列表,现在从第一个列表开始:


所以首先让我们尝试一般的复制方法:


copy=list_1


现在,如果您认为复制复制了list_1那么您可能错了,让我们检查一下:



The id() function shows us that both variables point to the same list object, i.e. they share this object.



print(id(copy))
print(id(list_1))


输出:


4329485320
4329485320


很惊讶?好吧,让我们探索一下:


因此我们知道python不会在变量中存储任何内容,变量只是引用对象而对象存储值。这里的对象是list但是我们通过两个不同的变量名创建了对同一个对象的两个引用。所以这两个变量都指向同一个对象:


所以,当你copy=list_1真正做它的时候:


[183]​​]]


这里的图像list_1和copy是两个变量名,但两个变量的对象相同,list


因此,如果您尝试修改复制列表,那么它也将修改原始列表,因为列表只有一个,无论您是从复制列表还是从原始列表中修改该列表,您都将修改该列表:


copy[0]="modify"

print(copy)
print(list_1)


输出:


['modify', '98']
['modify', '98']


所以它修改了原始列表:



  那么解决方案是什么?

  
  方案:



现在让我们转向复制列表的第二种pythonic方法:


copy_1=list_1[:]


现在这个方法解决了我们在第一期中遇到的问题让我们检查一下:


print(id(copy_1))
print(id(list_1))

4338792136
4338791432


因此,我们可以看到我们的两个列表具有不同的id,这意味着两个变量都指向不同的对象,所以这里实际发生的是:


[184]


现在让我们尝试修改列表,让我们看看我们是否还面临上一个问题:


copy_1[0]="modify"

print(list_1)
print(copy_1)


输出:


['01', '98']
['modify', '98']


因此,您可以看到它没有修改原始列表,它只修改了复制的列表,所以我们可以使用它。


所以现在我觉得我们已经完成了?等等我们也要复制第二个嵌套列表所以让我们试试pythonic方式:


copy_2=list_2[:]


所以list_2应该引用另一个对象,它是list_2的副本,让我们检查:


print(id((list_2)),id(copy_2))


我们得到输出:


4330403592 4330403528


现在我们可以假设两个列表都指向不同的对象,所以现在让我们尝试修改它,让我们看看它给出了我们想要的东西:


所以当我们尝试:


copy_2[0][1]="modify"

print(list_2,copy_2)


它给我们输出:


[**'01', 'modify'**] [**'01', 'modify'**]


现在,我们使用pythonic方式,这有点令人困惑,但我们仍面临同样的问题。


让我们理解它:


所以当我们这样做时:


copy_2=list_2[:]


我们实际上只复制外部列表,而不是嵌套列表,所以嵌套列表是两个列表的同一个对象,让我们检查:


print(id(copy_2[0]))
print(id(list_2[0]))


输出:


4329485832
4329485832


所以实际上当我们做copy_2=list_2[:]时会发生这种情况:


[185]


它创建列表的副本,但只有外部列表副本,而不是嵌套列表副本,嵌套列表对于两个变量都是相同的,因此如果您尝试修改嵌套列表,那么它也将修改原始列表,因为嵌套列表对象对于两者都是相同的嵌套列表。


那么解决方案是什么?


解决方案是deep copy


from copy import deepcopy
deep=deepcopy(list_2)


现在让我们检查一下:


print(id((list_2)),id(deep))


输出:


4322146056 4322148040


两个id都不同,现在让我们检查嵌套列表id:


print(id(deep[0]))
print(id(list_2[0]))


输出:


4322145992
4322145800


正如你可以看到两个id都不同所以我们可以假设两个嵌套列表现在指向不同的对象。


所以当你deep=deepcopy(list_2)实际发生的事情时:


[186]


因此,两个嵌套列表都指向不同的对象,并且它们现在具有单独的嵌套列表副本。


现在让我们尝试修改嵌套列表,让我们看看它是否解决了以前的问题:


所以如果我们这样做:


deep[0][1]="modify"
print(list_2,deep)


输出:


[**'01', '98'**] [**'01', 'modify'**]


因此,您可以看到它没有修改原始的嵌套列表,它只修改了复制的列表。


如果您喜欢我的详细答案,请通过提升来告诉我,
 如果您对此答案有任何疑问,请评论:)

其它参考12


让我感到惊讶的是,这还没有被提及,所以为了完整起见......


您可以使用splat operator执行列表解包:*,它还将复制列表中的元素。


old_list = [1, 2, 3]

new_list = [*old_list]

new_list.append(4)
old_list == [1, 2, 3]
new_list == [1, 2, 3, 4]


这种方法的明显缺点是它只能在Python 3.5+中使用。


虽然时间明智,但这似乎比其他常用方法表现更好。


x = [random.random() for _ in range(1000)]

%timeit a = list(x)
%timeit a = x.copy()
%timeit a = x[:]

%timeit a = [*x]

#: 2.47 µs ± 38.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
#: 2.47 µs ± 54.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
#: 2.39 µs ± 58.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

#: 2.22 µs ± 43.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

其它参考13


不确定这是否仍然是实际的,但同样的行为也适用于字典。看看这个例子。


a = {'par' : [1,21,3], 'sar' : [5,6,8]}
b = a
c = a.copy()
a['har'] = [1,2,3]

a
Out[14]: {'har': [1, 2, 3], 'par': [1, 21, 3], 'sar': [5, 6, 8]}

b
Out[15]: {'har': [1, 2, 3], 'par': [1, 21, 3], 'sar': [5, 6, 8]}

c
Out[16]: {'par': [1, 21, 3], 'sar': [5, 6, 8]}

其它参考14


请注意,在某些情况下,如果您已经定义了自己的自定义类并且想要保留属性,那么您应该使用copy.copy()copy.deepcopy()而不是替代方法,例如在Python 3中:


import copy

class MyList(list):
    pass

lst = MyList([1,2,3])

lst.name = 'custom list'

d = {
'original': lst,
'slicecopy' : lst[:],
'lstcopy' : lst.copy(),
'copycopy': copy.copy(lst),
'deepcopy': copy.deepcopy(lst)
}


for k,v in d.items():
    print('lst: {}'.format(k), end=', ')
    try:
        name = v.name
    except AttributeError:
        name = 'NA'
    print('name: {}'.format(name))


输出:


lst: original, name: custom list
lst: slicecopy, name: NA
lst: lstcopy, name: NA
lst: copycopy, name: custom list
lst: deepcopy, name: custom list

其它参考15


new_list = my_list[:]


new_list = my_list
试着理解这一点。让我们说my_list在位置X的堆内存中,即my_list指向X.现在通过赋值new_list = my_list你让new_list指向X.这被称为浅拷贝。


现在如果你指定new_list = my_list[:]你只需将my_list的每个对象复制到new_list。这称为Deep copy。


你可以这样做的另一种方式是:



  • new_list = list(old_list)

  • import copy new_list = copy.deepcopy(old_list)


其它参考16


一个非常简单的方法独立于python版本在已经给出的答案中缺失,你可以在大多数时间使用(至少我这样做):


new_list = my_list * 1       #Solution 1 when you are not using nested lists


但是,如果my_list包含其他容器(例如嵌套列表),则必须使用深度复制,如上文答案中从复制库中建议的那样。例如:


import copy
new_list = copy.deepcopy(my_list)   #Solution 2 when you are using nested lists


奖金:如果你不想复制元素使用(又称浅拷贝):


new_list = my_list[:]





让我们理解解决方案#1和解决方案#2之间的区别


>>> 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])


正如您所看到的,当我们不使用嵌套列表时,解决方案#1工作正常。让我们来看看当我们将解决方案#1应用于嵌套列表时会发生什么。


>>> from copy import deepcopy
>>> a = [range(i,i+4) for i in range(3)]
>>> a
[**0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5**]
>>> b = a*1
>>> c = deepcopy(a)
>>> for i in (a, b, c): print i   
[**0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5**]
[**0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5**]
[**0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5**]
>>> a[2].append('99')
>>> for i in (a, b, c): print i   
[**0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99**]
[**0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5, 99**]   #Solution#1 didn't work in nested list
[**0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5**]       #Solution #2 - DeepCopy worked in nested list

其它参考17


你可以在list()函数中使用bulit:


newlist=list(oldlist)


我认为这段代码会对你有所帮助。