【问题标题】:Changing one list unexpectedly changes another, too [duplicate]更改一个列表也会意外更改另一个列表[重复]
【发布时间】:2015-06-29 08:58:56
【问题描述】:

我有一个表格列表

v = [0,0,0,0,0,0,0,0,0]

我在代码中的某个地方

vec=v
vec[5]=5

这改变了vvec

>>> print vec
[0, 0, 0, 0, 0, 5, 0, 0, 0]
>>> print v
[0, 0, 0, 0, 0, 5, 0, 0, 0]

为什么v 会发生变化?

【问题讨论】:

  • 值得注意的是,这种行为不仅限于列表,它也可以在 dict 对象中观察到,如果它们是可变的,也会在元组上观察到。
  • @SimeonVisser 我不可能提前知道。如果我想用关键字指针搜索,我就不会发布这个问题了。

标签: python python-2.7


【解决方案1】:

Python 将vec = v 中的两个列表指向同一内存位置。

要复制列表,请使用vec = v[:]


这似乎都违反直觉。为什么不将复制列表设为默认行为?考虑情况

def foo():
    my_list = some_function()
    # Do stuff with my_list

您不希望my_list 包含与some_function 中创建的完全相同的列表,并且不让计算机花费额外的时间来创建副本。对于大型列表,复制数据可能需要一些时间。由于这个原因,Python 在赋值时不会复制列表。



杂项说明:

  • 如果您熟悉使用指针的语言。在内部,在生成的汇编语言中,vecv 只是引用内存中列表开始地址的指针。

  • 其他语言已经能够通过使用copy on write 来克服我提到的障碍,它允许对象共享内存直到它们被修改。不幸的是,Python 从未实现过这一点。

  • 有关复制列表或进行深复制的其他方式,请参阅List changes unexpectedly after assignment. Why is this and how can I prevent it?

【讨论】:

    【解决方案2】:

    因为 v 指向与内存中的 vec 相同的列表。

    如果你不想拥有它,你必须做一个

    from copy import deepcopy
    vec = deepcopy(v)
    

    vec = v[:]
    

    【讨论】:

    • 你不需要浅表的深拷贝
    【解决方案3】:

    为什么 v 会发生变化?

    vecv 都是引用。

    在编码vec = v 时,您将v 地址分配给vec。 因此更改v 中的数据也会“更改”vec

    如果您想拥有两个不同的数组,请使用:

    vec = list(v)
    

    【讨论】:

      【解决方案4】:

      你可以使用

      vec=v[:] #but
      

      “Alex Martelli 对此的看法(至少早在 2007 年)是,这是一种奇怪的语法,永远使用它没有意义。;)(在他看来,下一个更具可读性)。 "

      vec=list(v)
      

      我的意思是这是 Erez 的链接...“How to clone or copy a list in Python?

      【讨论】:

        【解决方案5】:

        运行这段代码,你就会明白为什么变量 v 会改变。

        a = [7, 3, 4]
        b = a
        c = a[:]
        b[0] = 10
        print 'a: ', a, id(a)
        print 'b: ', b, id(b)
        print 'c: ', c, id(c)
        

        此代码在我的解释器上打印以下输出:

        a:  [10, 3, 4] 140619073542552                                                                                                
        b:  [10, 3, 4] 140619073542552                                                                                                
        c:  [7, 3, 4] 140619073604136
        

        如您所见,列表 a 和 b 指向同一个内存位置。然而,列表 c 完全是一个不同的内存位置。你可以说变量 a 和 b 是同一个列表的别名。因此,对变量 a 或 b 所做的任何更改也将反映在另一个列表中,但不会反映在列表 c 中 希望这可以帮助! :)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-01-14
          • 2013-09-27
          相关资源
          最近更新 更多