Enquanto a duplicata proposta , o que o objeto Python Ellipsis faz? responde à pergunta em um pythoncontexto geral , seu uso em um nditerloop requer, eu acho, informações adicionais.
A atribuição regular em Python simplesmente altera uma referência no dicionário de variável local ou global em vez de modificar uma variável existente no local. Isso significa que simplesmente atribuir ax não colocará o valor no elemento da matriz, mas, em vez disso, mudará x de uma referência de elemento da matriz para uma referência ao valor atribuído. Para realmente modificar o elemento da matriz, x deve ser indexado com reticências.
Essa seção inclui seu exemplo de código.
Então, em minhas palavras, o x[...] = ...modifica xno local; x = ...teria quebrado o link para a nditervariável e não o alterado. É semelhante, x[:] = ...mas funciona com matrizes de qualquer dimensão (incluindo 0d). Nesse contexto, xnão é apenas um número, é um array.
Talvez a coisa mais próxima desta nditeriteração, sem nditeré:
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 tive que indexar e modificar a[i]diretamente. Eu não poderia ter usado x = 2*x,. Nesta iteração xé um escalar e, portanto, não mutável
In [669]: for i,x in np.ndenumerate(a):
...: x[...] = 2 * x
...
TypeError: 'numpy.int32' object does not support item assignment
Mas no nditercaso xé um array 0d e mutável.
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'> ()
...
E porque é 0d, x[:]não pode ser usado em vez dex[...]
----> 3 x[:] = 2 * x
IndexError: too many indices for array
Uma iteração de array mais simples também pode fornecer informações:
In [675]: for x in a:
...: print(x, x.shape)
...: x[:] = 2 * x
...:
[ 0816] (3,)
[243240] (3,)
isso itera nas linhas (1ª dimensão) de a. xé então uma matriz 1d e pode ser modificada com x[:]=...ou x[...]=....
E se eu adicionar o external_loopsinalizador da próxima seção , xagora é um array 1d e x[:] =funcionaria. Mas x[...] =ainda funciona e é mais geral. x[...]é usado todos os outros nditerexemplos.
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 iteração de linha simples (em uma matriz 2d):
In [675]: for x in a:
...: print(x, x.shape)
...: x[:] = 2 * x
...:
[ 0816] (3,)
[243240] (3,)
isso itera nas linhas (1ª dimensão) de a. xé então uma matriz 1d e pode ser modificada com x[:] = ...ou x[...] = ....
Leia e experimente esta nditerpágina do começo ao fim. Por si só, nditernão é tão útil em python. Isso não acelera a iteração - não até que você transporte seu código para cython. np.ndindexé uma das poucas numpyfunções não compiladas que usa nditer.
Respostas:
Enquanto a duplicata proposta , o que o objeto Python Ellipsis faz? responde à pergunta em um
python
contexto geral , seu uso em umnditer
loop requer, eu acho, informações adicionais.https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#modifying-array-values
Essa seção inclui seu exemplo de código.
Então, em minhas palavras, o
x[...] = ...
modificax
no local;x = ...
teria quebrado o link para anditer
variável e não o alterado. É semelhante,x[:] = ...
mas funciona com matrizes de qualquer dimensão (incluindo 0d). Nesse contexto,x
não é apenas um número, é um array.Talvez a coisa mais próxima desta
nditer
iteração, semnditer
é: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 tive que indexar e modificar
a[i]
diretamente. Eu não poderia ter usadox = 2*x
,. Nesta iteraçãox
é um escalar e, portanto, não mutávelIn [669]: for i,x in np.ndenumerate(a): ...: x[...] = 2 * x ... TypeError: 'numpy.int32' object does not support item assignment
Mas no
nditer
casox
é um array 0d e mutável.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'> () ...
E porque é 0d,
x[:]
não pode ser usado em vez dex[...]
----> 3 x[:] = 2 * x IndexError: too many indices for array
Uma iteração de array mais simples também pode fornecer informações:
In [675]: for x in a: ...: print(x, x.shape) ...: x[:] = 2 * x ...: [ 0 8 16] (3,) [24 32 40] (3,)
isso itera nas linhas (1ª dimensão) de
a
.x
é então uma matriz 1d e pode ser modificada comx[:]=...
oux[...]=...
.E se eu adicionar o
external_loop
sinalizador da próxima seção ,x
agora é um array 1d ex[:] =
funcionaria. Masx[...] =
ainda funciona e é mais geral.x[...]
é usado todos os outrosnditer
exemplos.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 iteração de linha simples (em uma matriz 2d):
In [675]: for x in a: ...: print(x, x.shape) ...: x[:] = 2 * x ...: [ 0 8 16] (3,) [24 32 40] (3,)
isso itera nas linhas (1ª dimensão) de
a
.x
é então uma matriz 1d e pode ser modificada comx[:] = ...
oux[...] = ...
.Leia e experimente esta
nditer
página do começo ao fim. Por si só,nditer
não é tão útil empython
. Isso não acelera a iteração - não até que você transporte seu código paracython
.np.ndindex
é uma das poucasnumpy
funções não compiladas que usanditer
.fonte