In [68]: arr = np.arange(5)
In [69]: arr
Out[69]: array([0, 1, 2, 3, 4])
查看 numpy 数组属性的一种方法是:
In [70]: arr.__array_interface__
Out[70]:
{'data': (139628245945184, False),
'strides': None,
'descr': [('', '<i8')],
'typestr': '<i8',
'shape': (5,),
'version': 3}
data 类似于其数据缓冲区的id,其中实际存储了值。我们不能在其他代码中使用这个数字,但它在检查 view 之类的东西时很有用。其余部分用于解释这些值。
arr 的 memory 是一个 40 字节长 (5*8) 的 c 数组。那在哪里对我们来说并不重要。 arr 中的任何 view 都将使用相同的数据缓冲区。 copy 将拥有自己的数据缓冲区。
在数组上迭代就像是一个一个地访问值:
In [71]: i = arr[1]
In [72]: i
Out[72]: 1
In [73]: type(i)
Out[73]: numpy.int64
此i 不是对a 元素的引用。它是具有相同值的新对象。它很像一个 0d 数组,具有许多相同的属性,包括:
In [74]: i.__array_interface__
Out[74]:
{'data': (25251568, False),
'strides': None,
'descr': [('', '<i8')],
'typestr': '<i8',
'shape': (),
'version': 3,
'__ref': array(1)}
这就是为什么在迭代中查看id 没有多大意义。这也是为什么在 numpy 数组上迭代比在列表上迭代慢的原因。我们强烈反对这样的迭代。
将其与列表进行对比,列表中的元素通过reference存储(在某种数据缓冲区中):
In [78]: a,b,c = 100,'b',{}
In [79]: id(a)
Out[79]: 9788064
In [80]: alist=[a,b,c]
In [81]: id(alist[0])
Out[81]: 9788064
该列表实际上包含a,或者如果您更喜欢对变量a 引用的同一对象的引用。请记住,Python 自始至终都是面向对象的。
总之,Python 列表包含引用。 Numpy 数组包含值,它自己的方法可以访问和操作这些值。有一个对象 dtype 确实包含引用,但我们不要去那里。