python中的副本列表

copy list in python

本问题已经有最佳答案,请猛点这里访问。

当我试图做一份清单的副本,并用清单的副本做一些事情的时候。不知怎么的,我的原始列表也被修改了。我已经研究了不同的内存分配和分配列表的不同方法。到目前为止没有运气…有什么想法吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
    row = 0
    column = 0
    table1 = copy.copy(table[:])

    temptable = []
    temptable = table[:]

    print id(table)
    print table
    print id(table1)
    print table1
    print id(temptable)
    print temptable

    for i in temptable:
        for j in i:
            if type(j) == str:
                temptable[row][column] = 0
            column = column + 1
        column = 0
        row = row + 1
    result=[]  

    for column in zip(*temptable):
        try:
                result.append(sum(map(int,column)))
            except ValueError:
                result.append(0)


    print table
    print table1
    print temptable

α/β的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
163783148
[[0, 'ZZZ', 'XXX', 'YYY', 'AAA', 0, 0], ['BBB', 1, 1, 0, 26, 28, 0], ['CCC', 26, 0, 0, 0, 26, 0], ['DDD', 0, 26, 0, 0, 26, 0], ['EEE', 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]]

163669036
[[0, 'ZZZ', 'XXX', 'YYY', 'AAA', 0, 0], ['BBB', 1, 1, 0, 26, 28, 0], ['CCC', 26, 0, 0, 0, 26, 0], ['DDD', 0, 26, 0, 0, 26, 0], ['EEE', 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]]

163783468
[[0, 'ZZZ', 'XXX', 'YYY', 'AAA', 0, 0], ['BBB', 1, 1, 0, 26, 28, 0], ['CCC', 26, 0, 0, 0, 26, 0], ['DDD', 0, 26, 0, 0, 26, 0], ['EEE', 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]]

[[0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 0, 26, 28, 0], [0, 26, 0, 0, 0, 26, 0], [0, 0, 26, 0, 0, 26, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]]

[[0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 0, 26, 28, 0], [0, 26, 0, 0, 0, 26, 0], [0, 0, 26, 0, 0, 26, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]]

[[0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 0, 26, 28, 0], [0, 26, 0, 0, 0, 26, 0], [0, 0, 26, 0, 0, 26, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0]]


原始列表包含内部列表:

1
2
3
[[0, 'ZZZ', 'XXX', 'YYY', 'AAA', 0, 0],
 ['BBB', 1, 1, 0, 26, 28, 0], ...
]

内部列表实际上存储为引用,即:

1
2
3
[ location-of-list-0,
  location-of-list-1, ...
]

复制列表时,实际上复制了对原始列表中存储的相同列表的引用列表。这被称为浅拷贝,因为它复制引用而不是内容。

使用深度复制创建一个完全独立的列表。

插图原始清单

enter image description here

浅拷贝

enter image description here

深拷贝

enter image description here


您还需要deepcopy来复制列表中的对象,而不仅仅是引用。


您还应该复制内部列表,这样deepcopy可以帮助您。


由于[:]只创建切片实际应用到的列表的一个拷贝切片,对对象的引用保持不变。使用deepcopy可以递归地复制每个可以指出的项目。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Foo:

    def __init__(self):
        self.name   ="unknown"

    def __repr__(self):
        return"Foo:" + self.name

    def __copy__(self):
        f = Foo()
        f.name = self.name
        return f

    def __deepcopy__(self, d):
        return self.__copy__()

lst = [Foo()]
lst[0].name ="My first foo"

lst2 = lst[:]
lst2.append(Foo())
lst2[1].name ="My second foo"

print lst
print lst2

output

[Foo: My first foo]
[Foo: My first foo, Foo: My second foo]

1
2
3
4
lst2[0].name ="I changed the first foo"

print lst
print lst2

output

[Foo: I changed the first foo]
[Foo: I changed the first foo, Foo: My second foo]

1
2
3
4
5
6
7
from copy import deepcopy
lst[0].name ="My first foo"
lst3 = deepcopy(lst)
lst3[0].name ="I changed the first foo again !"

print lst
print lst3

output

[Foo: I changed the first foo]
[Foo: I changed the first foo again !]

列表、元组等确实支持__copy____deepcopy__方法。