python - numpy 数组切片的意外结果(查看与复制)

标签 python arrays numpy scipy slice

我试图减少代码中的复制量,但在处理 numpy 数组切片和 View 时遇到了令人惊讶的行为,如中所述:

Scipy wiki page on copying numpy arrays

我偶然发现了以下行为,这对我来说是出乎意料的:

案例 1.:

import numpy as np
a = np.ones((3,3))
b = a[:,1:2]
b += 5
print a
print b.base is a

如预期的那样,输出:

array([[ 1.,  6.,  1.],
       [ 1.,  6.,  1.],
       [ 1.,  6.,  1.]])
True

情况 2:在一行中执行切片和添加时,情况看起来有所不同:

import numpy as np
a = np.ones((3,3))
b = a[:,1:2] + 5
print a
print b.base is a

令我惊讶的部分是 a[:,1:2] 似乎没有创建 View ,然后将其用作左侧参数,因此,输出:

array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])
False

也许有人可以阐明为什么这两种情况不同,我想我遗漏了什么。

解决方案:我忽略了一个明显的事实,即“+”运算符,而不是就地运算符“+=”,它总是会创建一个副本,所以它实际上不相关,而是切片其他比如何为 numpy 数组定义就地运算符。

为了说明这一点,以下生成与案例 2 相同的输出:

import numpy as np
a = np.ones((3,3))
b = a[:,1:2]
b = b + 5
print a
print b.base is a

最佳答案

以上内容与:

>>> a=np.arange(5)
>>> b=a
>>> b
array([0, 1, 2, 3, 4])

>>> b+=5
>>> a
array([5, 6, 7, 8, 9])
>>> b
array([5, 6, 7, 8, 9])

>>> b=b+5
>>> b
array([10, 11, 12, 13, 14])
>>> a
array([5, 6, 7, 8, 9])

至少在我看来,这完全是意料之中的行为。 b+=x 运算符调用 __iadd__ 重要的是首先尝试修改数组,因此它将更新 b 这仍然是 a 的一个 View 。 b=b+x 运算符调用 __add__ 创建新的临时数据,然后将其分配b

对于 a[i] +=b 序列是(在 numpy 中):

a.__setitem__(i, a.__getitem__(i).__iadd__(b))

关于python - numpy 数组切片的意外结果(查看与复制),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18155972/

相关文章:

python - 如何在 OS X 10.6 上构建 64 位 Python——只有 64 位,没有通用的废话

c++ - 带有指向数组指针的程序重新分配

arrays - Mpi4Py - 发送无副本的 numpy 子数组(非连续内存)

php - 将数组转换为 Ul-Li

python - Pandas 在 groupby 中设置值

python - 如何在seaborn线图中的特定点添加标记?

python - 是否有适用于 Python 3.x 的 Google Data API (gdata)?

python - 在 Pandas DataFrame 中的所有行上运行基于 numpy 的函数的快速替代方法

python - C API 中 Numpy datetime64 的转换

python - 优化Python中的内存使用: del obj or gc.收集()?