在子数组上迭代时,np.nditer不分配值

时间:2019-10-12 22:39:25

标签: arrays python-3.x numpy

当迭代数组用作子数组

时,在 np.nditer 内部的赋值方法期间主数组不会更新值

array = np.arange(20)

with np.nditer(array[np.nonzero(array)],
               op_flags=['readwrite']) as it:
    for x in it:
        x[...] = 5
array
  

array([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19])


在没有 np.nditer

的情况下,子数组分配出色
array[np.nonzero(array)] = 5
array
  

array([0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5])


使用临时数组可以解决此问题。

tmp_array = array[np.nonzero(array)]

array = np.arange(20)

with np.nditer(tmp_array,
               op_flags=['readwrite']) as it:
    for x in it:
        x[...] = 5

array[np.nonzero(array)] = tmp_array
array
  

array([0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5])

  1. np.nditer 使用子数组分配时,为什么主数组不更新值?
  2. np.nditer 中分配子数组时,是否有更方便的解决方法?

1 个答案:

答案 0 :(得分:1)

In [48]: arr = np.arange(20) 
    ...: with np.nditer(arr[np.nonzero(arr)], 
    ...:                op_flags=['readwrite']) as it: 
    ...:     for x in it: 
    ...:         x[...] = 5 
    ...: arr                                                                    
Out[48]: 
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19])

这不会更改arr,因为它没有在arr上进行迭代。相反,它在做:

In [49]: arr = np.arange(20) 
    ...: arr1 = arr[np.nonzero(arr)] 
    ...: with np.nditer(arr1, 
    ...:                op_flags=['readwrite']) as it: 
    ...:     for x in it: 
    ...:         x[...] = 5 
    ...: arr1                                                                   
Out[49]: array([5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5])
In [50]: _.shape                                                                
Out[50]: (19,)

arr1不是view的{​​{1}},它是一个选择,一个没有共享数据缓冲区的新数组。

如果要修改arr,则必须对其进行迭代,而不是副本。在循环内进行测试或任何其他幻想。

arr

但是为什么要使用In [51]: arr = np.arange(20) ...: with np.nditer(arr, ...: op_flags=['readwrite']) as it: ...: for x in it: ...: if x > 0: ...: x[...] = 5 ...: arr Out[51]: array([0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]) ?您已经知道如何使用非迭代方法进行这种选择性分配:

nditer

在这种情况下,分配array[np.nonzero(array)] = 5 紧随高级索引之后,Python使用=而不是array.__setitem__

在切片上进行迭代,arr.__getitem__确实会更改源:

view