numpy.nditer#
- class numpy.nditer(op, flags=None, op_flags=None, op_dtypes=None, order='K', casting='safe', op_axes=None, itershape=None, buffersize=0)[源代码]#
用于迭代数组的高效多维迭代器对象.要开始使用此对象,请参阅 introductory guide to array iteration .
- 参数:
- opndarray 或 array_like 序列
要迭代的数组.
- flagsstr 序列,可选
控制迭代器行为的标志.
buffered在需要时启用缓冲.c_index导致跟踪 C 顺序索引.f_index导致跟踪 Fortran 顺序索引.multi_index导致跟踪多重索引,或每个迭代维度具有一个索引的索引元组.common_dtype导致所有操作数都被转换为一个公共数据类型,必要时进行复制或缓冲.copy_if_overlap导致迭代器确定读取的操作数是否与写入的操作数重叠,并根据需要制作临时副本以避免重叠.在某些情况下可能会出现误报(不必要的复制).delay_bufalloc延迟缓冲区的分配,直到调用 reset().允许在将allocate操作数的值复制到缓冲区之前对其进行初始化.external_loop使得给定的values成为具有多个值的一维数组,而不是零维数组.当同时使用
buffered和external_loop时,grow_inner允许value数组的大小大于缓冲区的大小.ranged允许将迭代器限制为 iterindex 值的子范围.refs_ok允许迭代引用类型,例如对象数组.reduce_ok允许迭代被广播的readwrite操作数,也称为归约操作数.zerosize_ok允许 itersize 为零.
- op_flagslist of list of str, 可选
这是每个操作数的标志列表.至少必须指定
readonly,readwrite或writeonly之一.readonly表示操作数将仅被读取.readwrite表示操作数将被读取和写入.writeonly表示操作数将仅被写入.no_broadcast阻止操作数被广播.contig强制操作数数据是连续的.aligned强制操作数数据是对齐的.nbo强制操作数数据采用本机字节顺序.copy允许在需要时创建只读临时副本.updateifcopy允许在需要时创建读写临时副本.如果 op 参数中的数组为 None,
allocate将导致分配数组.no_subtype阻止allocate操作数使用子类型.arraymask表示此操作数是用作选择元素的掩码,以便写入设置了“writemasked”标志的操作数. 迭代器不强制执行此操作,但是当从缓冲区写回数组时,它仅复制此掩码指示的那些元素.writemasked表示仅当所选的arraymask操作数为 True 时,才会写入元素.overlap_assume_elementwise可用于标记仅以迭代器顺序访问的操作数,以便在使用copy_if_overlap时允许较不保守的复制.
- op_dtypesdtype 或 dtype(s) 的元组,可选
操作数所需的数据类型.如果启用了复制或缓冲,则数据将转换为/从其原始类型转换.
- order{‘C’, ‘F’, ‘A’, ‘K’},可选
控制迭代顺序.“C”表示 C 顺序,“F”表示 Fortran 顺序,“A”表示如果所有数组都是 Fortran 连续的则为“F”顺序,否则为“C”顺序,而“K”表示尽可能接近数组元素在内存中出现的顺序. 这也会影响
allocate操作数的元素内存顺序,因为它们被分配为与迭代顺序兼容. 默认为“K”.- casting{‘no’, ‘equiv’, ‘safe’, ‘same_kind’, ‘unsafe’}, 可选
控制在进行复制或缓冲时可能发生的数据类型转换种类. 不建议将此设置为“unsafe”,因为它可能会对累积产生不利影响.
‘no’ 表示根本不应转换数据类型.
‘equiv’ 表示仅允许字节顺序更改.
‘safe’ 表示只允许可以保留值的转换.
‘same_kind’ 表示只允许安全转换或同类转换,如 float64 到 float32.
‘unsafe’ 表示可以进行任何数据转换.
- op_axeslist of list of ints, 可选
如果提供,则对于每个操作数,为整数列表或 None.操作数的轴列表是从迭代器的维度到操作数的维度的映射. 可以为条目放置一个 -1 值,导致该维度被视为
newaxis.- itershape整数元组,可选
迭代器所需的形状. 这允许由 op_axes 映射且不对应于不同操作数的维度的维度的
allocate操作数获取不等于 1 的值.- buffersize整数,可选
当启用缓冲时,控制临时缓冲区的大小.设置为 0 表示默认值.
注释
nditer取代了flatiter.nditer背后的迭代器实现也通过 NumPy C API 公开.Python 公开了两种迭代接口,一种遵循 Python 迭代器协议,另一种则镜像 C 风格的 do-while 模式.在大多数情况下,原生 Python 方法更好,但如果需要迭代器的坐标或索引,请使用 C 风格的模式.
示例
下面是我们如何使用 Python 迭代器协议编写一个
iter_add函数:>>> import numpy as np
>>> def iter_add_py(x, y, out=None): ... addop = np.add ... it = np.nditer([x, y, out], [], ... [['readonly'], ['readonly'], ['writeonly','allocate']]) ... with it: ... for (a, b, c) in it: ... addop(a, b, out=c) ... return it.operands[2]
下面是相同的函数,但遵循 C 风格模式:
>>> def iter_add(x, y, out=None): ... addop = np.add ... it = np.nditer([x, y, out], [], ... [['readonly'], ['readonly'], ['writeonly','allocate']]) ... with it: ... while not it.finished: ... addop(it[0], it[1], out=it[2]) ... it.iternext() ... return it.operands[2]
这是一个外部乘积函数的示例:
>>> def outer_it(x, y, out=None): ... mulop = np.multiply ... it = np.nditer([x, y, out], ['external_loop'], ... [['readonly'], ['readonly'], ['writeonly', 'allocate']], ... op_axes=[list(range(x.ndim)) + [-1] * y.ndim, ... [-1] * x.ndim + list(range(y.ndim)), ... None]) ... with it: ... for (a, b, c) in it: ... mulop(a, b, out=c) ... return it.operands[2]
>>> a = np.arange(2)+1 >>> b = np.arange(3)+1 >>> outer_it(a,b) array([[1, 2, 3], [2, 4, 6]])
这是一个像 “lambda” ufunc 一样操作的示例函数:
>>> def luf(lamdaexpr, *args, **kwargs): ... '''luf(lambdaexpr, op1, ..., opn, out=None, order='K', casting='safe', buffersize=0)''' ... nargs = len(args) ... op = (kwargs.get('out',None),) + args ... it = np.nditer(op, ['buffered','external_loop'], ... [['writeonly','allocate','no_broadcast']] + ... [['readonly','nbo','aligned']]*nargs, ... order=kwargs.get('order','K'), ... casting=kwargs.get('casting','safe'), ... buffersize=kwargs.get('buffersize',0)) ... while not it.finished: ... it[0] = lamdaexpr(*it[1:]) ... it.iternext() ... return it.operands[0]
>>> a = np.arange(5) >>> b = np.ones(5) >>> luf(lambda i,j:i*i + j/2, a, b) array([ 0.5, 1.5, 4.5, 9.5, 16.5])
如果操作数标志
"writeonly"或"readwrite"被使用,则操作数可能是具有 WRITEBACKIFCOPY 标志的原始数据的视图.在这种情况下,nditer必须用作上下文管理器,或者在使用结果之前必须调用nditer.close方法.临时数据将在调用__exit__函数时写回原始数据,但不会在此之前写回:>>> a = np.arange(6, dtype='i4')[::-2] >>> with np.nditer(a, [], ... [['writeonly', 'updateifcopy']], ... casting='unsafe', ... op_dtypes=[np.dtype('f4')]) as i: ... x = i.operands[0] ... x[:] = [-1, -2, -3] ... # a still unchanged here >>> a, x (array([-1, -2, -3], dtype=int32), array([-1., -2., -3.], dtype=float32))
重要的是要注意,一旦迭代器退出,悬空引用(如示例中的 x )可能共享或不共享原始数据 a 的数据.如果写回语义处于活动状态,即如果 x.base.flags.writebackifcopy 为 True ,则退出迭代器将断开 x 和 a 之间的连接,写入 x 将不再写入 a .如果写回语义未处于活动状态,则 x.data 仍将指向 a.data 的某些部分,并且写入其中一个将影响另一个.
上下文管理和 close 方法出现在 1.15.0 版本中.
- 属性:
- dtypesdtype(s) 的元组
value 中提供的值的数据类型.如果启用了缓冲,这可能与操作数数据类型不同.仅在迭代器关闭之前有效.
- finishedbool
对操作数的迭代是否完成.
- has_delayed_bufallocbool
如果为 True,则迭代器是使用
delay_bufalloc标志创建的,并且尚未对其调用 reset() 函数.- has_indexbool
如果为 True,则迭代器是使用
c_index或f_index标志创建的,并且属性 index 可用于检索它.- has_multi_indexbool
如果为 True,则迭代器是使用
multi_index标志创建的,并且属性 multi_index 可用于检索它.- index
当使用
c_index或f_index标志时,此属性提供对索引的访问.如果访问且has_index为 False,则引发 ValueError.- iterationneedsapibool
迭代是否需要访问 Python API,例如,如果其中一个操作数是对象数组.
- iterindexint
与迭代顺序匹配的索引.
- itersizeint
迭代器的大小.
- itviews
内存中 operands 的结构化视图,与重新排序和优化的迭代器访问模式匹配.仅在迭代器关闭之前有效.
- multi_index
当使用
multi_index标志时,此属性提供对索引的访问.如果访问且has_multi_index为 False,则引发 ValueError.- ndimint
迭代器的维度.
- nopint
迭代器操作数的数量.
operands操作数的元组operands[ Slice ]
- shapetuple of ints
形状元组,迭代器的形状.
- value
当前迭代中
operands的值.通常,这是一个数组标量的元组,但如果使用了external_loop标志,则它是一个一维数组的元组.
方法
close()解析可写操作数中的所有写回语义.
copy()获取迭代器当前状态的副本.
debug_print()将
nditer实例的当前状态和调试信息打印到 stdout.如果在构造期间未使用“external_loop”,但需要使用,则此方法会修改迭代器的行为,使其如同指定了该标志一样.
iternext()检查是否还有迭代剩余,并执行单个内部迭代而不返回结果.
remove_axis(i, /)从迭代器中移除轴 i .
如果指定了“multi_index”标志,则将其删除,从而可以进一步优化内部迭代结构.
reset()将迭代器重置为其初始状态.