【问题标题】:Variable assignment and modification (in python) [duplicate]变量赋值和修改(在python中)[重复]
【发布时间】:2011-10-11 06:05:55
【问题描述】:

当我运行这个脚本时(Python v2.6):

a = [1,2]
b = a
a.append(3)
print a
>>>> [1,2,3]
print b
>>>> [1,2,3]

我希望 print b 输出 [1,2]。当我所做的只是改变a时,为什么b会改变? b 是否与 a 永久绑定?如果是这样,我可以让他们独立吗?怎么样?

【问题讨论】:

  • @Felix 我想​​说不完全是一个骗局——他不仅问如何克隆,还问为什么 Python 会以某种方式运行。
  • "Python has names" 是关于此行为的更好的教程/介绍的非常好的部分。
  • @thegrinner:是的,我有点太快了。只是暗示一下会更好。

标签: python list variables


【解决方案1】:

简答 - 指针。

当您键入b = a 时,它会将b 设置为查看a 查看的同一数组。您必须使用元素的副本创建一个新数组来分隔它们。在这种情况下,b = [n for n in a] 之类的东西可以正常工作。对于更复杂的操作,您可能需要查看http://docs.python.org/library/copy.html

【讨论】:

  • b = a[:] 也有效,而且更“pythonic”(或者他们这么说)
【解决方案2】:

Python 中的对象是通过引用存储的——您不是将a 的值分配给b,而是一个指向a 指向的对象的指针。

要模拟按值分配,您可以像这样复制:

import copy

b = copy.copy(a)

# now the code works as "expected"

请注意,这有性能劣势。

在数组的情况下,有一个依赖切片的特殊方法:

b = a[:]

# code also works as expected here

更新——除此之外,你可以使用一些对象的构造函数——这包括列表:

b = list(a)

【讨论】:

  • DiggyF 在下面的评论中指出了这一点 - 出于可读性原因和任何与 numpy 一起使用的原因,您需要将 b = a[:] 替换为 b = list(a)
【解决方案3】:

a 是指向列表[1,2] 的指针。

当你给b = a赋值时,b的值就是[1,2]列表的地址。

因此,当您执行a.append(3) 时,您实际上并没有更改a,而是更改了a 指向的列表。由于ab 都指向同一个列表,因此当您修改另一个时,它们似乎都会发生变化。

【讨论】:

    【解决方案4】:

    您可能想查看this 链接。你在这里遇到的问题是ab 都指向同一个内存位置,所以改变一个会改变另一个。相反,你想做这样的事情:

    a = [1,2]
    b = list(a)
    

    【讨论】:

    • 来自链接中的文章:“下次您看到 [:] 尝试将其替换为列表时,您的代码应该更具可读性。这样做,魔鬼在细节中。”。所以建议使用b=list(a)。这也是一个好主意,因为当人们从列表切换到 numpy 数组时,a[:] 将引用相同的数据。
    【解决方案5】:

    如果你只是想将列表 a 的内容复制到 b,而不是让 b 成为指向 a 的指针:

    b = a[:]
    

    使用切片运算符会将列表的内容复制到 b 中,这样您的示例将变为:

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

    【讨论】:

      【解决方案6】:

      Python 中的内存管理涉及一个私有堆内存位置,其中包含所有 Python 对象和数据结构。

      Python 的运行时只处理对对象的引用(它们都存在于堆中):Python 堆栈中的内容总是对存在于其他地方的值的引用。

      >>> a = [1, 2]
      

      >>> b = a
      

      >>> a.append(3)
      

      这里我们可以清楚的看到变量ba绑定到同一个对象上。

      您可以使用is 运算符来测试两个对象在物理上是否相同,这意味着它们在内存中是否具有相同的地址。这也可以使用id() 函数进行测试。

      >>> a is b
      >>> True
      >>> id(a) == id(b)
      >>> True
      

      因此,在这种情况下,您必须明确要求提供副本。 完成此操作后,两个不同的列表对象之间将不再有任何联系。

      >>> b = list(a)
      >>> a is b
      >>> False
      

      【讨论】:

        猜你喜欢
        • 2013-09-13
        • 2015-03-21
        • 1970-01-01
        • 2017-12-18
        • 2016-02-03
        • 1970-01-01
        • 2014-05-06
        • 1970-01-01
        相关资源
        最近更新 更多