Python:列表编辑问题

时间:2010-10-28 16:05:19

标签: python list

我的代码的简化版本:

sequence = [['WT_1', 'AAAAAAAA'], ['WT_2', 'BBBBBBB']]

def speciate(sequence):
    lineage_1 = []
    lineage_2 = []

    for i in sequence:
        lineage_1.append(i)
    for k in sequence:
        lineage_2.append(k)

    lineage_1[0][0] = 'L1_A'
    lineage_1[1][0] = 'L1_B'
    lineage_2[0][0] = 'L2_A'
    lineage_2[1][0] = 'L2_B'

    print lineage_1
    print lineage_2

speciate(sequence)

输出:

[['L2_A', 'AAAAAAAA'], ['L2_B','BBBBBBB']]
[['L2_A','AAAAAAAA'], ['L2_B','BBBBBBB']]

当我希望得到这个时:

[['L1_A', 'AAAAAAAA'], ['L1_B','BBBBBBB']]
[['L2_A','AAAAAAAA'], ['L2_B','BBBBBBB']]

有人知道问题是什么吗?

3 个答案:

答案 0 :(得分:2)

当你追加时,你必须做一个深拷贝(或者在这种情况下是浅拷贝)。否则lineage_1[0][0]lineage_2[0][0]引用相同的对象。

from copy import deepcopy
for i in sequence:
   lineage_1.append(deepcopy(i))
for k in sequence:
   lineage_2.append(deepcopy(k))

另请参阅:http://docs.python.org/library/copy.html

答案 1 :(得分:1)

您要在for循环中附加列表对象 - 相同列表对象(sequence[0])。

因此,当您修改该列表的第一个元素时:

lineage_1[0][0] = 'L1_A'
lineage_1[1][0] = 'L1_B'
lineage_2[0][0] = 'L2_A'
lineage_2[1][0] = 'L2_B'

您看到它在lineage_X列表中都显示为已修改,其中包含sequence[0]中列表的副本。

做类似的事情:

import copy
for i in sequence:
    lineage_1.append(copy.copy(i))
for k in sequence:
    lineage_2.append(copy.copy(k))

这将复制sequence的子列表,以便您不会出现此别名问题。 (如果真实代码具有更深的嵌套,则可以使用copy.deepcopy代替copy.copy。)

答案 2 :(得分:0)

考虑这个简单的例子:

>>> aa = [1, 2, 3]
>>> bb = aa
>>> bb[0] = 999
>>> aa
[999, 2, 3]

这里发生了什么?

“名称”,例如aabb,只需引用列表,即同一列表。因此,当您通过bb更改列表时,aa也会看到它。使用id显示了这一点:

>>> id(aa)
32343984
>>> id(bb)
32343984

现在,这正是您的代码中发生的事情:

for i in sequence:
    lineage_1.append(i)
for k in sequence:
    lineage_2.append(k)

您将相同列表的引用附加到lineage_1lineage_2