问题描述
import numpy as np
foo = np.zeros(1,dtype=int)
bar = np.zeros((10,1),dtype=int)
foo_copy = np.copy(foo)
bar[-1] = foo_copy
foo_copy[-1] = 10
print(foo_copy)
print(bar)
我期望 foo_copy
和 bar
的最后一个元素都包含值 10,但 bar
的最后一个元素仍然是一个包含值 0 的 np 数组。
[10]
[[0]
[0]
[0]
[0]
[0]
[0]
[0]
[0]
[0]
[0]] # <<--- why not 10?
或者在所有作业中,np 都会复制数据而我无法使用原始 ndarray 更改它?
如果是这样,有没有办法将最后一个元素保留为指向 foo_bar 的指针?
解决方法
numpy
数组具有数值,而不是引用(至少对于数值 dtypes
):
制作一维数组,并将其重塑为二维:
In [64]: bar = np.arange(12).reshape(4,3)
In [65]: bar
Out[65]:
array([[ 0,1,2],[ 3,4,5],[ 6,7,8],[ 9,10,11]])
另一个一维数组:
In [66]: foo = np.array([10])
In [67]: foo
Out[67]: array([10])
此分配是按值分配的:
In [68]: bar[1,1] = foo
In [69]: bar
Out[69]:
array([[ 0,11]])
也是这样,虽然值是 broadcasted
到整行:
In [70]: bar[2] = foo
In [71]: bar
Out[71]:
array([[ 0,[10,10],11]])
我们可以view
将二维数组作为一维数组。这是值实际存储方式的更接近表示(但在 c
字节数组中,12*8 字节长):
In [72]: bar1 = bar.ravel()
In [73]: bar1
Out[73]: array([ 0,2,3,5,9,11])
改变view
的一个元素会改变2d的对应元素:
In [74]: bar1[3] = 30
In [75]: bar
Out[75]:
array([[ 0,[30,11]])
虽然我们可以制作 object
dtype 数组,它像列表一样存储引用,但它们没有任何性能优势。
包含 bar
的“原始数据”的字节串:
In [76]: bar.tobytes()
Out[76]: b'\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00'
传说中的 numpy
速度来自于使用编译后的 c
代码处理这些原始数据。使用 Python 代码访问单个元素相对较慢。像 bar*3
这样的全数组操作速度很快。