NumPy 包含一个迭代器对象 numpy.nditer,它是一个高效的多维迭代器对象,用于迭代数组。每个元素都是使用标准 Python 迭代器接口一一提供的。

在下面的示例中,使用 arange() 函数创建数组,然后使用 nditer 用于迭代它。

import numpy as np

#创建一个数组
Arr = np.arange(10,25)
Arr = Arr.reshape(3,5)

#打印数组
print("原始数组为:")
print(Arr)

#使用 nditer 迭代数组
print("\n修改后的数组为:")
for i in np.nditer(Arr):
  print(i, end=" ") 

上述代码的输出将是:

原始数组为:
[[10 11 12 13 14]
 [15 16 17 18 19]
 [20 21 22 23 24]]

修改后的数组为:
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 

选择迭代顺序以匹配数组的内存布局使用标准 C 或 Fortran 排序的方法。这样做是为了提高访问效率,反映了这样一种想法:默认情况下,人们只想访问每个元素,而不关心特定的顺序。这可以通过迭代上述数组的转置来看出。

import numpy as np

#创建数组
Arr = np.arange(10,25)
Arr = Arr.reshape(3,5)

#打印数组
print("原始数组为:")
print(Arr)

#打印数组
print("\n转置后的数组为:")
print(Arr.T)

#迭代数组的转置
print("\n修改后的数组为:")
for i in np.nditer(Arr.T):
  print(i, end=" ") 

上述代码的输出将是:

原始数组为:
[[10 11 12 13 14]
 [15 16 17 18 19]
 [20 21 22 23 24]]

转置后的数组为:
[[10 15 20]
 [11 16 21]
 [12 17 22]
 [13 18 23]
 [14 19 24]]

修改后的数组为:
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 

迭代顺序

有例如,无论元素在内存中的布局如何,都必须以特定顺序访问数组的元素。 nditer 对象提供了一个 order 参数来控制迭代的这方面。默认值为 order='K' 以保持数组的现有顺序。对于 C 顺序,可以指定为 order='C',对于 Fortran 顺序,可以将其指定为 order='F'。

import numpy as np

#创建数组
Arr = np.arange(10,25)
Arr = Arr.reshape(3,5)

#打印数组
print("原始数组为:")
print(Arr)

#使用 order='K' 迭代数组
print("\n修改后的数组 (order='K'):")
for i in np.nditer(Arr, order='K'):
  print(i, end=" ")

#使用 order='C' 迭代数组
print("\n\n修改后的数组 (order='C'):")
for i in np.nditer(Arr, order='C'):
  print(i, end=" ")

#使用 order='F' 迭代数组
print("\n\n修改后的数组 (order='F'):")
for i in np.nditer(Arr, order='F'):
  print(i, end=" ") 

上述输出代码将是:

原始数组为:
[[10 11 12 13 14]
 [15 16 17 18 19]
 [20 21 22 23 24]]

修改后的数组 (order='K'):
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 

修改后的数组 (order='C'):
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 

修改后的数组 (order='F'):
10 15 20 11 16 21 12 17 22 13 18 23 14 19 24 

修改数组值

nditer对象还有另一个可选参数,称为op_flags。默认情况下,nditer 将输入操作数视为只读对象。为了能够修改数组元素,必须使用 op_flags=['readwrite'] 或 op_flags=['writeonly'] 指定读写或只写模式i>.

import numpy as np

#创建数组
Arr = np.arange(10,25)
Arr = Arr.reshape(3,5)

#打印数组
print("原始数组为:")
print(Arr)

#修改数组的元素
for x in np.nditer(Arr, op_flags=['readwrite']):
  x[...] = 2*x

#打印数组
print("\n修改后的数组为:")
print(Arr) 

上述代码的输出将是:

原始数组为:
[[10 11 12 13 14]
 [15 16 17 18 19]
 [20 21 22 23 24]]

修改后的数组为:
[[20 22 24 26 28]
 [30 32 34 36 38]
 [40 42 44 46 48]] 

外部循环

nditer对象还有另一个可选的参数名为flags,可以取以下值:

参数说明
c_index要跟踪的 C 顺序索引。
f_index要跟踪的 Fortran 顺序索引。
multi_index要跟踪的多索引或每个迭代维度一个索引的元组。
external_loop使给定的值成为具有多个值的一维数组,而不是零维数组。
range允许迭代器 限制为 iterindex 值的子范围。

在下面的例子中,迭代器遍历每一列对应的一维数组。

import numpy as np

#创建数组
Arr = np.arange(10,25)
Arr = Arr.reshape(3,5)

#打印数组
print("原始数组为:")
print(Arr)

#使用external_loop迭代数组
print("\n修改后的数组为:")
for i in np.nditer(Arr, flags = ['external_loop'], order = 'F'):
  print(i, end=" ") 

上述代码的输出将是:

原始数组为:
[[10 11 12 13 14]
 [15 16 17 18 19]
 [20 21 22 23 24]]

修改后的数组为:
[10 15 20] [11 16 21] [12 17 22] [13 18 23] [14 19 24] 

广播数组迭代

如果两个数组可广播,组合的 nditer 对象能够同时迭代它们。

在下面的示例中,nditer 对象用于迭代同时处理数组arr1和arr2。 arr1 的维度为 (2x3),arr2 的维度为 (1x3)。

import numpy as np

#创建第一个数组
arr1 = np.arange(10,70,10)
arr1 = arr1.reshape(2,3)

#创建第二个数组
arr2 = np.array([1, 2, 3], dtype = int)

#打印数组
print("arr1 为:")
print(arr1)
print("\narr2 为:")
print(arr2)

#同时迭代两个数组
print("\n修改后的数组为:")
for x,y in np.nditer([arr1, arr2]):
  print("%d:%d" % (x,y), end=" ") 

上述代码的输出将是:

arr1 为:
[[10 20 30]
 [40 50 60]]

arr2 为:
[1 2 3]

修改后的数组为:
10:1 20:2 30:3 40:1 50:2 60:3