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)[源代码]#
高效的多维迭代器对象,用于迭代数组。要开始使用此对象,请参阅数组迭代入门指南。
- 参数:
- opndarray 或 array_like 序列
要迭代的数组。
- flags字符串序列,可选
控制迭代器行为的标志。
buffered启用所需的缓冲。c_index导致跟踪 C 顺序索引。f_index导致跟踪 F 顺序索引。multi_index导致跟踪多重索引,或一个包含每个迭代维度的索引的元组。common_dtype导致所有操作数都转换为公共数据类型,并在需要时进行复制或缓冲。copy_if_overlap导致迭代器确定读取操作数是否与写入操作数重叠,并在需要时创建临时副本以避免重叠。在某些情况下,可能出现误报(不必要的复制)。delay_bufalloc延迟缓冲区的分配,直到调用 reset()。允许allocate操作数在将值复制到缓冲区之前进行初始化。external_loop导致给定的values是包含多个值的一维数组,而不是零维数组。grow_inner当同时使用buffered和external_loop时,允许value数组的大小大于缓冲区大小。ranged允许将迭代器限制在迭代索引值的一个子范围内。refs_ok启用对引用类型的迭代,例如对象数组。reduce_ok启用对被广播的readwrite操作数的迭代,也称为归约操作数。zerosize_ok允许itersize为零。
- op_flags字符串列表的列表,可选
这是每个操作数的标志列表。至少必须指定
readonly、readwrite或writeonly中的一个。readonly表示操作数仅将被读取。readwrite表示操作数将被读取和写入。writeonly表示操作数仅将被写入。no_broadcast防止操作数被广播。contig强制操作数数据是连续的。aligned强制操作数数据对齐。nbo强制操作数数据为本机字节序。copy允许在需要时创建临时只读副本。updateifcopy允许在需要时创建临时读写副本。allocate当op参数中的数组为 None 时,会导致分配该数组。no_subtype防止allocate操作数使用子类型。arraymask表示此操作数是用于在写入具有 'writemasked' 标志的操作数时选择元素的掩码。迭代器不强制执行此操作,但在将缓冲区写回数组时,它仅复制此掩码指示的元素。writemasked表示仅写入所选arraymask操作数为 True 的元素。overlap_assume_elementwise可用于标记仅按迭代器顺序访问的操作数,以允许在存在copy_if_overlap时进行不太保守的复制。
- op_dtypesdtype 或 dtype 的元组,可选
操作数的必需数据类型。如果启用了复制或缓冲,数据将被转换为/从其原始类型转换。
- order{‘C’, ‘F’, ‘A’, ‘K’}, optional
控制迭代顺序。“C”表示 C 顺序,“F”表示 Fortran 顺序,“A”表示如果所有数组都为 Fortran 连续,则为“F”顺序,否则为“C”顺序,“K”表示尽可能接近数组元素在内存中出现的顺序。这也会影响
allocate操作数的元素内存顺序,因为它们是为兼容迭代顺序而分配的。默认值为“K”。- casting{‘no’, ‘equiv’, ‘safe’, ‘same_kind’, ‘unsafe’}, optional
控制在进行复制或缓冲时可能发生的数据类型转换的种类。不建议将此设置为“unsafe”,因为它可能对累加产生负面影响。
‘no’ 表示数据类型不得进行任何转换。
‘equiv’ 表示只允许进行字节顺序更改。
‘safe’ 表示只允许进行可以保留值的转换。
‘same_kind’ 表示只允许安全的转换或同一类别的转换,例如从 float64 到 float32。
‘unsafe’ 表示可以进行任何数据转换。
- op_axes整数列表的列表,可选
如果提供,则是每个操作数的整数列表或 None。操作数的轴列表是从迭代器的维度到操作数维度的映射。可以将条目设置为 -1,使该维度被视为
newaxis。- itershape整数元组,可选
迭代器的期望形状。这允许
allocate操作数,其中一个维度通过 op_axes 映射,但不对应于另一个操作数的维度,为该维度获得一个不等于 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必须用作上下文管理器,或者必须在__exit__函数调用之前调用nditer.close方法,但在此之前不能。>>> 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 的元组
在
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]
- shape整数元组
形状元组,迭代器的形状。
- value
当前迭代时
operands的值。通常,这是一个数组标量的元组,但如果使用了external_loop标志,则它是一个包含一维数组的元组。
方法