Mientras que el duplicado propuesto ¿Qué hace el objeto Python Ellipsis? responde a la pregunta en un pythoncontexto general , su uso en un nditerbucle requiere, creo, información adicional.
La asignación regular en Python simplemente cambia una referencia en el diccionario de variable local o global en lugar de modificar una variable existente en su lugar. Esto significa que simplemente asignar ax no colocará el valor en el elemento de la matriz, sino que cambiará x de ser una referencia de elemento de matriz a ser una referencia al valor que asignó. Para modificar realmente el elemento de la matriz, x debe indexarse con puntos suspensivos.
Esa sección incluye su ejemplo de código.
Entonces, en mis palabras, las x[...] = ...modificaciones xen el lugar; x = ...habría roto el enlace a la nditervariable y no lo habría cambiado. Es como, x[:] = ...pero funciona con matrices de cualquier dimensión (incluido 0d). En este contexto, xno es solo un número, es una matriz.
Quizás lo más cercano a esta nditeriteración, sin nditeres:
In [667]: for i, x in np.ndenumerate(a):
...: print(i, x)
...: a[i] = 2 * x
...:
(0, 0) 0
(0, 1) 1
...
(1, 2) 5
In [668]: a
Out[668]:
array([[ 0, 2, 4],
[ 6, 8, 10]])
Observe que tuve que indexar y modificar a[i]directamente. No podría haber usado x = 2*x,. En esta iteración xes un escalar y, por lo tanto, no es mutable
In [669]: for i,x in np.ndenumerate(a):
...: x[...] = 2 * x
...
TypeError: 'numpy.int32' object does not support item assignment
Pero en el nditercaso xes una matriz 0d y mutable.
In [671]: for x in np.nditer(a, op_flags=['readwrite']):
...: print(x, type(x), x.shape)
...: x[...] = 2 * x
...:
0 <class 'numpy.ndarray'> ()
4 <class 'numpy.ndarray'> ()
...
Y debido a que es 0d, x[:]no se puede usar en lugar dex[...]
----> 3 x[:] = 2 * x
IndexError: too many indices for array
Una iteración de matriz más simple también podría brindar información:
In [675]: for x in a:
...: print(x, x.shape)
...: x[:] = 2 * x
...:
[ 0816] (3,)
[243240] (3,)
esto itera en las filas (primera atenuación) de a. xes entonces una matriz 1d y se puede modificar con x[:]=...o x[...]=....
Y si agrego la external_loopbandera de la siguiente sección , xahora es una matriz 1d y x[:] =funcionaría. Pero x[...] =todavía funciona y es más general. x[...]se utiliza todos los demás nditerejemplos.
In [677]: for x in np.nditer(a, op_flags=['readwrite'], flags=['external_loop']):
...: print(x, type(x), x.shape)
...: x[...] = 2 * x
[ 01632486480] <class 'numpy.ndarray'> (6,)
Compare esta iteración de fila simple (en una matriz 2d):
In [675]: for x in a:
...: print(x, x.shape)
...: x[:] = 2 * x
...:
[ 0816] (3,)
[243240] (3,)
esto itera en las filas (primera atenuación) de a. xes entonces una matriz 1d y se puede modificar con x[:] = ...o x[...] = ....
Lea y experimente con esta nditerpágina hasta el final. Por sí solo, nditerno es tan útil en python. No acelera la iteración, no hasta que transfiera su código a cython. np.ndindexes una de las pocas numpyfunciones no compiladas que utiliza nditer.
Respuestas:
Mientras que el duplicado propuesto ¿Qué hace el objeto Python Ellipsis? responde a la pregunta en un
python
contexto general , su uso en unnditer
bucle requiere, creo, información adicional.https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#modifying-array-values
Esa sección incluye su ejemplo de código.
Entonces, en mis palabras, las
x[...] = ...
modificacionesx
en el lugar;x = ...
habría roto el enlace a landiter
variable y no lo habría cambiado. Es como,x[:] = ...
pero funciona con matrices de cualquier dimensión (incluido 0d). En este contexto,x
no es solo un número, es una matriz.Quizás lo más cercano a esta
nditer
iteración, sinnditer
es:In [667]: for i, x in np.ndenumerate(a): ...: print(i, x) ...: a[i] = 2 * x ...: (0, 0) 0 (0, 1) 1 ... (1, 2) 5 In [668]: a Out[668]: array([[ 0, 2, 4], [ 6, 8, 10]])
Observe que tuve que indexar y modificar
a[i]
directamente. No podría haber usadox = 2*x
,. En esta iteraciónx
es un escalar y, por lo tanto, no es mutableIn [669]: for i,x in np.ndenumerate(a): ...: x[...] = 2 * x ... TypeError: 'numpy.int32' object does not support item assignment
Pero en el
nditer
casox
es una matriz 0d y mutable.In [671]: for x in np.nditer(a, op_flags=['readwrite']): ...: print(x, type(x), x.shape) ...: x[...] = 2 * x ...: 0 <class 'numpy.ndarray'> () 4 <class 'numpy.ndarray'> () ...
Y debido a que es 0d,
x[:]
no se puede usar en lugar dex[...]
----> 3 x[:] = 2 * x IndexError: too many indices for array
Una iteración de matriz más simple también podría brindar información:
In [675]: for x in a: ...: print(x, x.shape) ...: x[:] = 2 * x ...: [ 0 8 16] (3,) [24 32 40] (3,)
esto itera en las filas (primera atenuación) de
a
.x
es entonces una matriz 1d y se puede modificar conx[:]=...
ox[...]=...
.Y si agrego la
external_loop
bandera de la siguiente sección ,x
ahora es una matriz 1d yx[:] =
funcionaría. Perox[...] =
todavía funciona y es más general.x[...]
se utiliza todos los demásnditer
ejemplos.In [677]: for x in np.nditer(a, op_flags=['readwrite'], flags=['external_loop']): ...: print(x, type(x), x.shape) ...: x[...] = 2 * x [ 0 16 32 48 64 80] <class 'numpy.ndarray'> (6,)
Compare esta iteración de fila simple (en una matriz 2d):
In [675]: for x in a: ...: print(x, x.shape) ...: x[:] = 2 * x ...: [ 0 8 16] (3,) [24 32 40] (3,)
esto itera en las filas (primera atenuación) de
a
.x
es entonces una matriz 1d y se puede modificar conx[:] = ...
ox[...] = ...
.Lea y experimente con esta
nditer
página hasta el final. Por sí solo,nditer
no es tan útil enpython
. No acelera la iteración, no hasta que transfiera su código acython
.np.ndindex
es una de las pocasnumpy
funciones no compiladas que utilizanditer
.fuente