Que signifie" trois points " en Python lors de l'indexation de ce qui ressemble à un nombre?
Quel est le sens de x[... ci-dessous?
a = np.arange(6).reshape(2,3)
for x in np.nditer(a, op_flags=['readwrite']):
x[...] = 2 * x
1 réponses
alors que le duplicata proposé Que fait L'objet Python Ellipsis? répond à la question dans un contexte général python
, son utilisation dans une boucle nditer
nécessite, je pense, des informations supplémentaires.
https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#modifying-array-values
assignation régulière en Python change simplement une référence dans le local ou variable globale dictionnaire au lieu de modifier une variable existante en place. Cela signifie que le simple fait d'assigner à x ne placera pas la valeur dans l'élément du tableau, mais fera passer x d'une référence d'élément de tableau à une référence à la valeur que vous avez assignée. Pour modifier réellement l'élément du tableau, x devrait être indexé avec l'ellipse.
cette section comprend votre exemple de code.
ainsi dans mes mots, le x[...] = ...
modifie le x
en place; le x = ...
aurait brisé le lien avec la variable nditer
et ne l'aurait pas changé. C'est comme x[:] = ...
mais fonctionne avec des tableaux de n'importe quelle dimension (y compris 0d). Dans ce contexte, x
n'est pas juste un nombre, c'est un tableau.
peut-être la chose la plus proche de cette itération nditer
, sans nditer
est:
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]])
notez que j'ai dû indexer et modifier a[i]
directement. Je n'aurais pas pu utiliser x = 2*x
. Dans cette itération x
est un scalaire, et donc pas mutable
In [669]: for i,x in np.ndenumerate(a):
...: x[...] = 2 * x
...
TypeError: 'numpy.int32' object does not support item assignment
mais dans le nditer
cas x
est un tableau 0d, et 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'> ()
...
et parce qu'il est 0d, x[:]
ne peut pas être utilisé à la place de x[...]
----> 3 x[:] = 2 * x
IndexError: too many indices for array
une itération plus simple du tableau pourrait aussi donner une idée:
In [675]: for x in a:
...: print(x, x.shape)
...: x[:] = 2 * x
...:
[ 0 8 16] (3,)
[24 32 40] (3,)
cette itération se fait sur les lignes (1er dim) de a
. x
est donc un tableau 1d, et peut être modifié avec x[:]=...
ou x[...]=...
.
et si j'ajoute le drapeau external_loop
de la section suivante , , x
est maintenant un tableau 1d, et x[:] =
fonctionnerait. Mais x[...] =
fonctionne toujours et est plus général. x[...]
est utilisé tous les autres nditer
exemples.
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,)
Comparer cette ligne simple itération (sur un tableau 2d):
In [675]: for x in a:
...: print(x, x.shape)
...: x[:] = 2 * x
...:
[ 0 8 16] (3,)
[24 32 40] (3,)
cette itération se fait sur les lignes (1er dim) de a
. x
est donc un tableau 1d, et peut être modifié avec x[:] = ...
ou x[...] = ...
.
lisez et expérimentez avec cette page nditer
jusqu'à la fin. En soi, nditer
n'est pas très utile dans python
. Il n'accélère pas l'itération - pas jusqu'à ce que vous portiez votre code à cython
. np.ndindex
est l'une des rares fonctions non compilées numpy
qui utilise nditer
.