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
32
demandé sur Paul Panzer 2017-02-12 20:24:28

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 .

27
répondu hpaulj 2018-02-05 16:55:54