gpt4 book ai didi

python - 比较 NumPy 对象引用

转载 作者:行者123 更新时间:2023-12-04 20:32:12 25 4
gpt4 key购买 nike

我想了解 NumPy 的行为。

当我尝试获取 NumPy 数组的内部数组的引用,然后将其与对象本身进行比较时,我得到返回值 False .

这是示例:

In [198]: x = np.array([[1,2,3], [4,5,6]])
In [201]: x0 = x[0]
In [202]: x0 is x[0]
Out[202]: False

另一方面,对于 Python native 对象,返回的是 True .
In [205]: c = [[1,2,3],[1]]    
In [206]: c0 = c[0]
In [207]: c0 is c[0]
Out[207]: True

我的问题是,这是 NumPy 的预期行为吗?如果是这样,如果我想创建 NumPy 数组的内部对象的引用,我该怎么办。

最佳答案

二维切片

当我第一次写这篇文章时,我构造并索引了一个一维数组。但是 OP 使用的是二维数组,所以 x[0]是一个“行”,原始的切片。

In [81]: arr = np.array([[1,2,3], [4,5,6]])
In [82]: arr.__array_interface__['data']
Out[82]: (181595128, False)

In [83]: x0 = arr[0,:]
In [84]: x0.__array_interface__['data']
Out[84]: (181595128, False) # same databuffer pointer
In [85]: id(x0)
Out[85]: 2886887088
In [86]: x1 = arr[0,:] # another slice, different id
In [87]: x1.__array_interface__['data']
Out[87]: (181595128, False)
In [88]: id(x1)
Out[88]: 2886888888

我之前写的关于切片的内容仍然适用。索引单个元素,如 arr[0,0]与一维数组的工作方式相同。

这个 2d arr 与 1d arr.ravel() 具有相同的数据缓冲区;形状和步幅不同。与 view的区别, copyitem仍然适用。

在 C 中实现二维数组的一种常见方法是拥有一个指向其他数组的指针数组。 numpy需要一个不同的, strided方法,只有一个平面数据数组,并使用 shapestrides参数来实现横向。所以一个子数组需要它自己的 shapestrides以及指向共享数据缓冲区的指针。

一维数组索引

我将尝试说明索引数组时发生的情况:
In [51]: arr = np.arange(4)

数组是一个具有各种属性的对象,例如形状和数据缓冲区。缓冲区将数据存储为字节(在 C 数组中),而不是 Python 数字对象。您可以使用以下命令查看有关阵列的信息:
In [52]: np.info(arr)
class: ndarray
shape: (4,)
strides: (4,)
itemsize: 4
aligned: True
contiguous: True
fortran: True
data pointer: 0xa84f8d8
byteorder: little
byteswap: False
type: int32

或者
In [53]: arr.__array_interface__
Out[53]:
{'data': (176486616, False),
'descr': [('', '<i4')],
'shape': (4,),
'strides': None,
'typestr': '<i4',
'version': 3}

一个是十六进制的数据指针,另一个是十进制的。我们通常不直接引用它。

如果我索引一个元素,我会得到一个新对象:
In [54]: x1 = arr[1]
In [55]: type(x1)
Out[55]: numpy.int32
In [56]: x1.__array_interface__
Out[56]:
{'__ref': array(1),
'data': (181158400, False),
....}
In [57]: id(x1)
Out[57]: 2946170352

它具有数组的一些属性,但不是全部。例如,您不能分配给它。还要注意它的 'data' 值是完全不同的。

从同一个地方做另一个选择 - 不同的 id 和不同的数据:
In [58]: x2 = arr[1]
In [59]: id(x2)
Out[59]: 2946170336
In [60]: x2.__array_interface__['data']
Out[60]: (181143288, False)

此外,如果我此时更改数组,它不会影响先前的选择:
In [61]: arr[1] = 10
In [62]: arr
Out[62]: array([ 0, 10, 2, 3])
In [63]: x1
Out[63]: 1
x1x2没有相同的 id ,因此不会与 is 匹配,他们不使用 arr数据缓冲区。没有记录表明这两个变量源自 arr .

slicing有可能得到一个 view原始数组,
In [64]: y = arr[1:2]
In [65]: y.__array_interface__
Out[65]:
{'data': (176486620, False),
'descr': [('', '<i4')],
'shape': (1,),
....}
In [66]: y
Out[66]: array([10])
In [67]: y[0]=4
In [68]: arr
Out[68]: array([0, 4, 2, 3])
In [69]: x1
Out[69]: 1

它的数据指针比 arr大4个字节- 也就是说,它指向同一个缓冲区,只是一个不同的位置。和改变 y确实改变了 arr (但不是独立的 x1 )。

我什至可以对这个项目进行 0d View
In [71]: z = y.reshape(())
In [72]: z
Out[72]: array(4)
In [73]: z[...]=0
In [74]: arr
Out[74]: array([0, 0, 2, 3])

在 Python 代码中,我们通常不使用这样的对象。当我们使用 c-apicython是否可以直接访问数据缓冲区。 nditer是一种迭代机制,适用于这样的 0d 对象(在 Python 或 c-api 中)。在 cython typed memoryviews对低级访问特别有用。

http://cython.readthedocs.io/en/latest/src/userguide/memoryviews.html

https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html

https://docs.scipy.org/doc/numpy/reference/c-api.iterator.html#c.NpyIter

按元素==

回复评论, Comparing NumPy object references

np.array([1]) == np.array([2]) will return array([False], dtype=bool)


==为数组定义为元素操作。它比较各个元素的值并返回一个匹配的 bool 数组。

如果需要在标量上下文(例如 if )中使用此类比较,则需要将其减少为单个值,如 np.allnp.any .
is测试比较对象 id(不仅仅是 numpy 对象)。它在实际编码中的值(value)有限。我最常在 is None 之类的表达式中使用它,其中 None是一个具有唯一 id 的对象,并且不能很好地用于相等测试。

关于python - 比较 NumPy 对象引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43885090/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com