NumPy 提供了一个 nditer 迭代器对象,它可以配合 for 循环完成对数组元素的遍历。
下面看一组示例,使用 arange() 函数创建一个 3*4 数组,并使用 nditer 生成迭代器对象。
示例1:
import numpy as np
a = np.arange(0,60,5)
a = a.reshape(3,4)
#使用nditer迭代器,并使用for进行遍历
for x in np.nditer(a):
print(x)
输出结果:
在内存中,Numpy 数组提供了两种存储数据的方式,分别是 C-order(行优先顺序)与 Fortrant-order(列优先顺序)。那么 nditer 迭代器又是如何处理具有特定存储顺序的数组呢?其实它选择了一种与数组内存布局一致的顺序,之所以这样做,是为了提升数据的访问效率。
在默认情况下,当我们遍历数组中元素的时候,不需要考虑数组的存储顺序,这一点可以通过遍历上述数组的转置数组来验证。
示例 2:
import numpy as np
a = np.arange(0,60,5)
a = a.reshape(3,4)
#a的转置数组
b = a.T
print (b)
for x in np.nditer(b):
print(x,end=",")
输出结果:
从示例 1、2 的输出结果可以看出,a 和 a.T 的遍历顺序是一样的,也就是说,它们在内存中的存储顺序是一样的。
下面以 C 样式访问转置数组的副本。示例 3 如下:
import numpy as np
a = np.arange(0,60,5).reshape(3,4)
#copy方法生成数组副本
for x in np.nditer(a.T.copy(order='C')):
print (x, end=", " )
输出结果:
通过示例 3 可知 a.T.copy(order = 'C') 的遍历结果与示例 1、2 的数组遍历结果不一样。究其原因,就是因为它们在内存中的存储方式不一样。
您可以通过 nditer 对象的order参数来指定数组的遍历的顺序。示例 4 如下:
import numpy as np
a = np.arange(0,60,5)
a = a.reshape(3,4)
print(a)
for x in np.nditer(a, order = 'C'):
print (x,end=",")
for x in np.nditer(a, order = 'F'):
print (x,end=",")
输出结果如下:
nditer 对象提供了一个可选参数op_flags,它表示能否在遍历数组时对元素进行修改。它提供了三种模式,如下所示:
只读模式,在这种模式下,遍历时不能修改数组中的元素。
读写模式,遍历时可以修改元素值。
只写模式,在遍历时可以修改元素值。
示例如下:
import numpy as np
a = np.arange(0,60,5)
a = a.reshape(3,4)
print ("原数组是:",a)
for x in np.nditer(a, op_flags=['readwrite']):
x[...]=2*x
print ('修改后的数组是:',a)
最后输出结果如下:
nditer 对象的构造函数有一个“flags”参数,它可以接受以下参数值(了解即可):
参数值 | 描述说明 |
---|---|
c_index | 可以跟踪 C 顺序的索引。 |
f_index | 可以跟踪 Fortran 顺序的索引。 |
multi_index | 每次迭代都会跟踪一种索引类型。 |
external_loop | 返回的遍历结果是具有多个值的一维数组。 |
示例 6 如下:
import numpy as np
a = np.arange(0,60,5)
a = a.reshape(3,4)
print("原数组",a)
#修改后数组
for x in np.nditer(a, flags = ['external_loop'], order = 'F'):
print(x)
结果输出:
如果两个数组都能够被广播,那么 nditer 对象就可以同时对它们迭代。
假设数组 a 的维度是 3*4,另一个数组 b 的维度是 1*4 (即维度较小的数组 b 可以被广播到数组 a 中),示例如下:
import numpy as np
a = np.arange(0,60,5)
a = a.reshape(3,4)
print (a)
b = np.array([1, 2, 3, 4], dtype = int)
print (b)
#广播迭代
for x,y in np.nditer([a,b]):
print ("%d:%d" % (x,y),end=",")
输出结果是: