Python numpy数组分配问题

Python numpy数组分配问题,python,arrays,numpy,Python,Arrays,Numpy,我在Python2.6.5中遇到了一个关于Numpy的奇怪问题。我分配一个numpy数组,然后将一个新变量等同于它。当我对新数组执行任何操作时,原始数组的值也会更改。为什么呢?请参见下面的示例。请指教我,因为我对Python和一般编程都相当陌生 -苏扬 >>> import numpy as np >>> a = np.array([[1,2],[3,4]]) >>> b = a >>> b array([[1, 2],

我在Python2.6.5中遇到了一个关于Numpy的奇怪问题。我分配一个numpy数组,然后将一个新变量等同于它。当我对新数组执行任何操作时,原始数组的值也会更改。为什么呢?请参见下面的示例。请指教我,因为我对Python和一般编程都相当陌生

-苏扬

>>> import numpy as np
>>> a = np.array([[1,2],[3,4]])
>>> b = a
>>> b
array([[1, 2],
       [3, 4]])
>>> c = a
>>> c
array([[1, 2],
       [3, 4]])
>>> c[:,1] = c[:,1] + 5
>>> c

array([[1, 7],
       [3, 9]])
>>> b
array([[1, 7],
       [3, 9]])
>>> a
array([[1, 7],
       [3, 9]])

这其实根本不是问题;这是Python中数组(和其他对象)的工作方式

请这样想:您在代码示例中创建的数组是位于内存中某个位置的对象。但是,您不能通过告诉Python在内存中的何处查找它来在程序中使用它;你必须给它起个名字。当你写作时

a = np.array([[1,2],[3,4]])
b = a.copy()
您既要创建数组,也要创建一个引用它的名称,
a
。从那时起,Python就知道
a
指的是“内存地址0x123674283”(或其他什么)。Python运行时中有一个内部表(如果我没记错的话,称为“符号表”)包含所有这些信息,因此在运行上述Python代码行之后,该表将包含

...,
'a' : 0x123674283,
...
将一个变量的值赋给另一个变量时,如

b = a

Python不会复制整个数组,因为如果它是一个大数组,则需要很长时间。而是转到符号表,将
a
的内存地址复制到
b
表中的新行。所以你最后和

...,
'a' : 0x123674283,
...,
'b' : 0x123674283,
...
你看,
a
b
实际上指的是内存中的同一个位置,即同一个对象。对其中一个的任何更改都会反映在另一个中,因为它们只是同一事物的两个名称

如果要实际创建数组的副本,必须调用一个方法来显式执行该操作。Numpy数组有一个
copy
方法,可用于此目的。所以如果你写

a = np.array([[1,2],[3,4]])
b = a.copy()
然后Python将首先实际创建数组的副本-也就是说,它留出一个新的内存区域,比如在地址0x123904381处,然后转到内存地址0x123674283,并将数组的所有值从内存的后一部分复制到前一部分。所以你在记忆中有两个不同的地方有相同的内容

...,
'a' : 0x123674283,
...,
'b' : 0x123904381,
...

现在,当您更改
b
的一个元素时,该更改不会显示在
a
中,因为
a
b
不再引用计算机内存的同一部分。由于阵列数据有两个独立的副本,因此可以更改其中一个副本而不影响另一个副本。

简单地说,变量赋值会创建对现有对象的新引用

  A = object   # A points to object in memory
  B = A        # B points to the same object

非常感谢您的精彩描述。不用说,这解决了问题,但我真的很感谢你花时间解释问题。你启发了我!“Python不复制整个数组,因为如果它是一个大数组,那么它需要很长时间。”——我想说的是它不需要花费更多的时间,而且如果你不以这种方式实现,更多的是需要引入一个单独的指针类型,而那些复杂的事情。C++语言,
b=a
是指针赋值。不是赋值。