【问题标题】:What exactly is happening when I copy and then edit this list?当我复制然后编辑此列表时到底发生了什么?
【发布时间】:2011-11-23 22:13:01
【问题描述】:

我完全不知道为什么会这样:

A = [[1,0], [2,2]]
B = list(A)

print('start A:', A, 'start B:', B)
A[0][0] = 999
print('end A:', A, 'end B:', B)

这会返回:

start A: [[1, 0], [2, 2]] start B: [[1, 0], [2, 2]]
end A: [[999, 0], [2, 2]] end B: [[999, 0], [2, 2]]

列表 A 和 B 最终是相同的,即使我从 A 中明确复制了 B。这只发生在我执行 A[0][0] = 999; 之类的操作时。如果我用 A[0] = 999 替换它,那么最后 A 和 B 是不同的。

这背后的原因是什么,有什么办法可以在不影响B的情况下以这种方式改变A?

【问题讨论】:

    标签: python list python-3.x


    【解决方案1】:

    您正在创建原始列表的浅拷贝,这是一个新列表,其中包含对与原始列表相同的对象的新引用。

    修改新列表对象不会改变原始列表。修改新列表中的对象确实修改旧列表中的对象,因为它们是相同的。

    要获得一个完全独立的列表,请使用copy.deepcopy() 创建一个深拷贝

    【讨论】:

      【解决方案2】:

      A 和 B 都包含相同的两个列表。

      你的代码大致相当于这个:

      x = [1, 0]
      y = [2, 2]
      
      A = [x, y]
      B = [x, y]
      

      A[0][0] = 999 操作实际上只是在执行x[0] = 999。也就是说,它不会修改 A 本身,它会修改列表x 的第一个元素。由于 A 和 B 都引用了 x,因此两者都会看到更改。

      【讨论】:

        【解决方案3】:

        像你做的一个简单的复制操作是,它只复制一个深度的项目并且不会递归到嵌套结构中。你需要

        >>> import copy
        >>> A = [[1,0], [2,2]]
        >>> B = copy.deepcopy(A)
        >>> print('start A:', A, 'start B:', B)
        start A: [[1, 0], [2, 2]] start B: [[1, 0], [2, 2]]
        >>> A[0][0] = 999
        >>> print('end A:', A, 'end B:', B)
        end A: [[999, 0], [2, 2]] end B: [[1, 0], [2, 2]]
        

        【讨论】:

          【解决方案4】:

          AB 是您计算机中同一块内存的两个不同名称。

          AB 是两个独立的列表对象,但 A[0]B[0] 是计算机中同一块内存的两个不同名称。从解释器尝试以下操作:

          id(B)
          id(A)
          id(B[0])
          id(A[0])
          

          【讨论】:

          • 不,他们不是。它们是单独的列表对象。
          【解决方案5】:

          Python 代码操作 referencesobjects

          分配给一个变量只是绑定一个名称来引用一个对象。

          列表由一堆对对象的引用组成。 list(A) 查找在A 中引用的所有对象,并创建一个包含对所有相同对象的引用的新列表。所以如果A 是一个列表列表,list(A) 会创建一个新列表,其中引用了A 中的相同列表。因此,A 和新列表都可以看到更改任何子列表。

          copy.deepcopy 的存在可以帮助您解决这个问题,当您需要某个东西的完整“深层”副本时。

          一旦您学会将 Python 代码视为像这样操作对对象的引用,您就会直观地理解何时代码最终可能会像这样从多个地方引用同一个对象,尽管可能总会有一些晦涩难懂的情况让你大吃一惊。

          【讨论】:

            猜你喜欢
            • 2019-10-03
            • 2022-11-27
            • 2011-01-21
            • 1970-01-01
            • 1970-01-01
            • 2016-11-06
            • 2010-09-15
            • 1970-01-01
            • 2011-09-12
            相关资源
            最近更新 更多