代码之家  ›  专栏  ›  技术社区  ›  Ashwin Nanjappa

如何制作复杂列表的完全非共享副本?(深度复制是不够的)

  •  6
  • Ashwin Nanjappa  · 技术社区  · 15 年前

    请看一下以下Python代码:

    a = [1, 2, 3]
    b = [4, 5, 6]
    c = [[a, b], [b, a]] # [[[1, 2, 3], [4, 5, 6]], [[4, 5, 6], [1, 2, 3]]]
    c[0][0].append(99)   # [[[1, 2, 3, 99], [4, 5, 6]], [[4, 5, 6], [1, 2, 3, 99]]]
    

    请注意如何修改 c 99 附于 c[0][0] c[1][1] . 我猜这是因为Python非常聪明 提到 对于 c[0][0] . (这是他们的

    问题: C 这样它的列表元素就可以安全地在本地修改了?上面只是一个例子,我真正的问题有一个更复杂的列表,但有一个类似的问题。

    (很抱歉上面的问题格式不正确。Python大师请随意修改问题或标记以更好地表达此查询。)

    5 回复  |  直到 12 年前
        1
  •  8
  •   Ashwin Nanjappa    15 年前

    当你想要一个副本时,你显式地制作了一个副本——神秘的副本 [:] “全部切片”形式是惯用的,但我最喜欢的是更可读的显式调用方法 list .

    c 是以错误的方式构建的(使用引用,而不是对您希望能够独立修改的列表的浅拷贝),最好的方法是修复它的构建方式(为什么要构建错误,然后努力修复它?!),但如果这超出了您的控制范围,则可以撤消损坏--只需循环即可 C (如果需要,递归地),使用索引,将相关子列表重新分配给它们的副本。例如,如果你确信 C 的结构是两级的,正如您所指出的,您可以保存自己而无需递归:

    def fixthewronglymadelist(c):
      for topsublist in c:
        for i, L in enumerate(topsublist):
          topsublist[i] = list(L)
    

    不管其他答案如何, copy.deepcopy 如果你所得到的只是做错了的东西,你就很难屈从于这个特殊的目的 C copy.deepcopy(c) 将仔细复制c的拓扑结构,包括对同一子列表的多个引用!:-)

        2
  •  8
  •   Ashwin Nanjappa    15 年前

    要将现有列表转换为不共享任何内容的列表,可以递归复制该列表。

    deepcopy 内部的 引用文件作为引用文件,而不是副本。

    def unshared_copy(inList):
        if isinstance(inList, list):
            return list( map(unshared_copy, inList) )
        return inList
    
    alist = unshared_copy(your_function_returning_lists())
    

    请注意,这假定数据作为列表列表(任意嵌套)返回。 如果容器的类型不同(例如numpy数组、DICT或用户类),则可能需要对此进行更改。

        3
  •  5
  •   Pesto    15 年前

    根据您的情况,您可能希望与 deep copy 这是名单上的一部分。

        4
  •  5
  •   Stephan202 Alex Martelli    15 年前

    [:] :

    >>> a = [1, 2]
    >>> b = a[:]
    >>> b.append(9)
    >>> a
    [1, 2]
    

    交替地,使用 copy or deepcopy :

    >>> import copy
    >>> a = [1, 2]
    >>> b = copy.copy(a)
    >>> b.append(9)
    >>> a
    [1, 2]
    

    复制 适用于列表以外的对象。对于列表,其效果与 a[:] . 深度复制 尝试递归地复制嵌套元素,因此是一个更“彻底”的操作 .

        5
  •  1
  •   Michael Dillon    15 年前

    要了解Stephan在工作中的建议,请比较以下两个输出:

    a = [1, 2, 3]
    b = [4, 5, 6]
    c = [[a, b], [b, a]]
    c[0][0].append(99)
    print c
    print "-------------------"
    a = [1, 2, 3]
    b = [4, 5, 6]
    c = [[a[:], b[:]], [b[:], a[:]]]
    c[0][0].append(99)
    print c
    

    结果如下:

    [[[1, 2, 3, 99], [4, 5, 6]], [[4, 5, 6], [1, 2, 3, 99]]]
    -------------------
    [[[1, 2, 3, 99], [4, 5, 6]], [[4, 5, 6], [1, 2, 3]]]