一尘不染

分配后列表意外更改。如何克隆或复制它以防止这种情况?

python

在使用new_list = my_list,任何修改new_list改变my_list每次。为什么会这样,如何克隆或复制列表以防止出现此情况?


阅读 199

收藏
2021-01-20

共1个答案

一尘不染

使用new_list = my_list,您实际上没有两个列表。分配只是将引用复制到列表,而不是实际列表,因此将两者复制new_listmy_list在分配后引用同一列表。

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

您可以使用内建list.copy()方法(自Python 3.3起可用):

new_list = old_list.copy()

您可以将其切片:

new_list = old_list[:]

Alex Martelli对此的看法(至少是在2007年)是,这是一种怪异的语法,永远不要使用它。;)(在他看来,下一个更具可读性)。

您可以使用内置list()函数:

new_list = list(old_list)

您可以使用generic copy.copy()

import copy
new_list = copy.copy(old_list)

这比list()因为必须找出old_listfirst的数据类型要慢一些。

如果列表包含对象,并且您也想复制它们,请使用generic copy.deepcopy()

import copy
new_list = copy.deepcopy(old_list)

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

例:

import copy

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

    def __repr__(self):
        return 'Foo({!r})'.format(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\nlist.copy(): %r\nslice: %r\nlist(): %r\ncopy: %r\ndeepcopy: %r'
      % (a, b, c, d, e, f))

结果:

original: ['foo', Foo(5), 'baz']
list.copy(): ['foo', Foo(5)]
slice: ['foo', Foo(5)]
list(): ['foo', Foo(5)]
copy: ['foo', Foo(5)]
deepcopy: ['foo', Foo(1)]
2021-01-20