Qual é o significado de x[...]
abaixo?
a = np.arange(6).reshape(2,3)
for x in np.nditer(a, op_flags=['readwrite']):
x[...] = 2 * x
Qual é o significado de x[...]
abaixo?
a = np.arange(6).reshape(2,3)
for x in np.nditer(a, op_flags=['readwrite']):
x[...] = 2 * x
Respostas:
Enquanto a duplicata proposta , o que o objeto Python Ellipsis faz? responde à pergunta em um python
contexto geral , seu uso em um nditer
loop requer, eu acho, informações adicionais.
https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#modifying-array-values
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 x
no local; x = ...
teria quebrado o link para a nditer
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, 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 nditer
caso 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
...:
[ 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 com x[:]=...
ou x[...]=...
.
E se eu adicionar o external_loop
sinalizador da próxima seção , x
agora é um array 1d e x[:] =
funcionaria. Mas x[...] =
ainda funciona e é mais geral. x[...]
é usado todos os outros nditer
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 com x[:] = ...
ou x[...] = ...
.
Leia e experimente esta nditer
página do começo ao fim. Por si só, nditer
nã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 numpy
funções não compiladas que usa nditer
.