1 逐个访问数组元素
使用nditer可以完成逐个访问数组中的元素。
a = np.arange(4).reshape(2, 2)
for i in a:
print(i)
for i in np.nditer(a):
print(i)
结果:
[0 1]
[2 3]
0
1
2
3
对于一维数组结果一样,但是多维就有区别了
2 控制迭代顺序
nditer对象提供了一个order参数来控制迭代顺序。其参数order有三个可选参数:K,F,C
具有上述行为的默认值是order ='K’以保持现有订单。 对于C顺序,可以使用order ='C’覆盖它,对于Fortran顺序,可以使用order ='F’覆盖它。
其中“K”是默认的,其结果与与原来的没有区别,逐个读取元素;
“C”:C order,即行序优先;;
“F”:Fortran order,即列序优先;
2.1二维
a = np.arange(6).reshape(2, 3)
print(a)
for i in np.nditer(a, order='C'):
print(i)
print("---------")
for i in np.nditer(a, order='F'):
print(i)
print("---------")
for i in np.nditer(a, order='K'):
print(i)
结果:
[[0 1 2]
[3 4 5]]
0
1
2
3
4
5
---------
0
3
1
4
2
5
---------
0
1
2
3
4
5
可以看出二维情况下"F"参数确实就是可以看过按列读取元素
2.2三维
a = np.arange(18).reshape(2, 3, 3)
print(a)
for i in np.nditer(a, order='C'):
print(i)
print("---------")
for i in np.nditer(a, order='F'):
print(i)
print("---------")
for i in np.nditer(a, order='K'):
print(i)
结果:
[[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]]
[[ 9 10 11]
[12 13 14]
[15 16 17]]]
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
---------
0
9
3
12
6
15
1
10
4
13
7
16
2
11
5
14
8
17
---------
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
注意三维数组列序优先时的读取顺序。
3 修改数组值
并不推荐这种方法来修改数组值,可以作为参考
默认情况下,nditer将输入数组视为只读对象。 要修改数组元素,必须指定读写或只写模式。 这是用每操作数标志控制的。
Python中的常规赋值只是更改本地或全局变量字典中的引用,而不是修改现有变量。 这意味着简单地分配给x不会将值放入数组的元素中,而是将x作为数组元素引用切换为对指定值的引用。 要实际修改数组的元素,x应该用省略号索引。
a = np.arange(6).reshape(2, 3)
for x in np.nditer(a, op_flags=['readwrite']):
x[...] = 2*x
print(a)
[[ 0 2 4]
[ 6 8 10]]
4 使用外部循环
在目前为止的所有示例中,a的元素由迭代器一次提供一个,因为所有循环逻辑都是迭代器的内部逻辑。 虽然这很简单方便,但效率不高。 更好的方法是将一维最内层循环移动到迭代器外部的代码中。 这样,NumPy的矢量化操作可以用在被访问元素的较大块上。
nditer将尝试提供尽可能大的内部循环块。 通过强制’C’和’F’顺序,我们得到不同的外部循环大小。 通过指定迭代器标志来启用此模式。
a = np.arange(6).reshape(2, 3)
for x in np.nditer(a, flags=['external_loop'], order='C'):
print(x)
print("--------------")
for x in np.nditer(a, flags=['external_loop'], order='F'):
print(x)
结果:注意行序优先中输出的一个数组,而不是一个个的数字元素
[0 1 2 3 4 5]
--------------
[0 3]
[1 4]
[2 5]
5 跟踪索引或多索引
在迭代期间,你可能希望在计算中使用当前元素的索引。 例如,你可能希望按内存顺序访问数组的元素,然后使用C顺序,Fortran顺序或多维索引来查找不同数组中的值。
5.1multi_index
下面代码中order参数根据自己需要选择,也可以不写默认按行逐个读取元素
a = np.arange(6).reshape(2, 3)
it = np.nditer(a, flags=['multi_index'], order="F")
while not it.finished:
print("%d < %s>" %(it[0], it.multi_index))
it.iternext()
结果: it.multi_index代表元素的索引,以元组形式输出
0 < (0, 0)>
3 < (1, 0)>
1 < (0, 1)>
4 < (1, 1)>
2 < (0, 2)>
5 < (1, 2)>
5.2 f_index
a = np.arange(6).reshape(2, 3)
it = np.nditer(a, flags=['f_index'])
while not it.finished:
print("%d < %d>" % (it[0], it.index))
it.iternext()
结果:索引的编号,以列序优先
0 < 0>
1 < 2>
2 < 4>
3 < 1>
4 < 3>
5 < 5>
6 缓冲数组元素
通过启用缓冲模式,迭代器提供给内部循环的块可以变得更大,从而显着减少Python解释器的开销。 在强制Fortran迭代顺序的示例中,当启用缓冲时,内部循环可以一次性查看所有元素。
a = np.arange(6).reshape(2, 3)
for x in np.nditer(a, flags=['external_loop','buffered'], order='F'):
print(x)
输出:
[0 3 1 4 2 5]
7 广播数组迭代
代码:
a = np.arange(3)
b = np.arange(6).reshape(2,3)
for x, y in np.nditer([a,b]):
print("%d:%d" % (x,y))
输出:
0:0
1:1
2:2
0:3
1:4
2:5