在循环中切片NumPy数组

时间:2016-03-17 09:03:06

标签: python arrays numpy

我需要一个很好的解释(参考)来解释(for)循环中的NumPy切片。我有三个案子。

def example1(array):
    for row in array:
        row = row + 1
    return array

def example2(array):
    for row in array:
        row += 1
    return array

def example3(array):
    for row in array:
        row[:] = row + 1
    return array

一个简单的案例:

ex1 = np.arange(9).reshape(3, 3)
ex2 = ex1.copy()
ex3 = ex1.copy()

返回:

>>> example1(ex1)
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

>>> example2(ex2)
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

>>> example3(ex3)
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

可以看出,第一个结果与第二个和第三个结果不同。

2 个答案:

答案 0 :(得分:4)

第一个例子:

您提取一行并向其中添加1。然后你重新定义 指针 row,而不是array包含的内容!所以它不会影响原始数组。

第二个例子:

你进行就地操作 - 显然这会影响原始数组 - 只要它是一个数组。

如果您正在进行双循环,它将不再起作用:

def example4(array):
    for row in array:
        for column in row:
            column += 1
    return array

example4(np.arange(9).reshape(3,3))
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

这不起作用,因为你没有调用np.ndarray的{​​{1}}(修改数组指向的数据),而python __iadd__的{​​{1} }。因此,此示例仅起作用,因为您的行是numpy数组。

第三个例子:

int这被解释为类似于__iadd__这样的工作,这会影响原始数组。

底线

如果您使用可变对象(例如row[:] = row + 1row[0] = row[0]+1, row[1] = row[1]+1, ...),则需要小心改变的内容。这样的对象只有到实际数据存储在内存中的位置 - 因此更改此指针list)不会影响保存的数据。您需要按照指针(直接通过np.ndarrayexample1)或间接通过[:]example3)来更改已保存的数据。

答案 1 :(得分:3)

在第一个代码中,您不对新计算的行执行任何操作;你重新绑定名称row,并且不再与数组连接。

在第二个和第三个中,你不重新绑定,而是为旧变量赋值。使用+=调用一些内部函数,这取决于您让它作用的对象的类型。请参阅以下链接。

如果在右侧编写row + 1,则会计算新数组。在第一种情况下,您告诉python为其指定名称 row(并忘记之前称为row的原始对象)。在第三个中,新数组被写入旧row的切片。

如需进一步阅读,请按照@Thiru上述问题的评论链接。或者阅读assignment and rebinding in general...