numpy数组切两次

时间:2015-08-18 03:24:34

标签: python arrays numpy slice

我不确定我理解为什么这不起作用:

a = np.zeros((10, ))

# first slicing array
pos1 = np.zeros((10, ), dtype=np.bool)
pos1[::2] = True

a[pos1] = 1.
print a
# returns [ 1.  0.  1.  0.  1.  0.  1.  0.  1.  0.]


# second slicing array
pos2 = np.zeros((5, ), dtype=np.bool)
pos2[::2] = True

a[pos1][pos2] = 2.

print a
# still returns [ 1.  0.  1.  0.  1.  0.  1.  0.  1.  0.]

为什么第二次切片不会影响整个阵列? 我认为a[pos1]只是一个"视图"原始数组的子部分...我错过了什么?

(这个例子只是一个没有实际用处的简单例子,它只是试图理解我使用这种语法的原因很多而且我没有预料到这个结果)

2 个答案:

答案 0 :(得分:2)

与最近Numpy doesn't change value of an array element after masking

中的问题相同

您正在使用布尔掩码,因此a[pos1]是副本,而不是切片。

第一组有效,因为它是对__setitem__的直接调用:

a[pos1] = 1.
a.__setitem__(pos1) = 1

第二个不是因为set适用于a[pos1],副本:

a[pos1][pos2] = 2.
a.__getitem__(pos1).__setitem__(pos2)

a[::2][pos2]=3确实有效,因为a[::2]是一个切片 - 即使它生成的值与a[pos1]相同。

检查某些内容是副本还是视图的一种方法是查看数组的数据指针

 a.__array_interface__['data']
 a[pos1].__array_interface__['data'] # will be different
 a[::2].__array_interface__['data']  # should be the same

答案 1 :(得分:0)

当我们定义以下三个函数时,请查看python字节代码(dis的输出):

In [187]: def b():
    a[pos1][pos2]=2
    return a

In [188]: dis.dis(b)
  2           0 LOAD_CONST               1 (2)
              3 LOAD_GLOBAL              0 (a)
              6 LOAD_GLOBAL              1 (pos1)
              9 BINARY_SUBSCR       
             10 LOAD_GLOBAL              2 (pos2)
             13 STORE_SUBSCR        

  3          14 LOAD_GLOBAL              0 (a)
             17 RETURN_VALUE        

In [189]: b()
Out[189]: array([ 1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.])




In [190]: def c():
    e=a.copy()
    e[pos1][pos2]=2
    return e

In [191]: dis.dis(c)
  2           0 LOAD_GLOBAL              0 (a)
              3 LOAD_ATTR                1 (copy)
              6 CALL_FUNCTION            0
              9 STORE_FAST               0 (e)

  3          12 LOAD_CONST               1 (2)
             15 LOAD_FAST                0 (e)
             18 LOAD_GLOBAL              2 (pos1)
             21 BINARY_SUBSCR       
             22 LOAD_GLOBAL              3 (pos2)
             25 STORE_SUBSCR        

  4          26 LOAD_FAST                0 (e)
             29 RETURN_VALUE 

In [191]: c()
Out[191]: array([ 1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.])




In [192]: def d():
    f=a[pos1]
    f[pos2]=2
    return f

In [193]: dis.dis(d)
  2           0 LOAD_GLOBAL              0 (a)
              3 LOAD_GLOBAL              1 (pos1)
              6 BINARY_SUBSCR       
              7 STORE_FAST               0 (f)

  3          10 LOAD_CONST               1 (2)
             13 LOAD_FAST                0 (f)
             16 LOAD_GLOBAL              2 (pos2)
             19 STORE_SUBSCR        

  4          20 LOAD_FAST                0 (f)
             23 RETURN_VALUE  

In [194]: d()
Out[194]: array([ 2.,  1.,  2.,  1.,  2.])

从反汇编代码中,每次执行a[pos1][pos2]=2赋值时,它确实存储在堆栈的顶部,但随后返回全局(情况1)或本地(情况2)变量。 当您拆分操作时(案例3),解释器似乎突然想起它只是将值存储在堆栈中而不需要重新加载它。