Comment utilisez-vous la syntaxe de découpage des points de suspension en Python?

Réponses:

102

Ellipsis, ou ... n'est pas une fonctionnalité cachée, c'est juste une constante. C'est assez différent de, disons, javascript ES6 où il fait partie de la syntaxe du langage. Aucune classe intégrée ou structure de langage Python ne l'utilise.

La syntaxe dépend donc entièrement de vous, ou de quelqu'un d'autre, ayant écrit du code pour le comprendre.

Numpy l'utilise, comme indiqué dans la documentation . Quelques exemples ici .

Dans votre propre classe, vous l'utiliseriez comme ceci:

>>> class TestEllipsis(object):
...     def __getitem__(self, item):
...         if item is Ellipsis:
...             return "Returning all items"
...         else:
...             return "return %r items" % item
... 
>>> x = TestEllipsis()
>>> print x[2]
return 2 items
>>> print x[...]
Returning all items

Bien sûr, il y a la documentation python et la référence du langage . Mais ceux-ci ne sont pas très utiles.

nosklo
la source
6
semble assez cassé puisque la manière "correcte" de dire tous les éléments est >>> x [:] >>> x [:, 1: 2]
Ronny
30
@Ronny: Le but était de démontrer une utilisation personnalisée d'Ellipsis.
nosklo
7
Les liens semblent rompus.
SwiftsNamesake
231

Les points de suspension sont utilisés dans numpy pour découper des structures de données de plus grande dimension.

Il est conçu pour signifier à ce stade, insérer autant de tranches complètes ( :) pour étendre la tranche multidimensionnelle à toutes les dimensions .

Exemple :

>>> from numpy import arange
>>> a = arange(16).reshape(2,2,2,2)

Maintenant, vous avez une matrice à 4 dimensions d'ordre 2x2x2x2. Pour sélectionner tous les premiers éléments de la 4ème dimension, vous pouvez utiliser la notation points de suspension

>>> a[..., 0].flatten()
array([ 0,  2,  4,  6,  8, 10, 12, 14])

ce qui équivaut à

>>> a[:,:,:,0].flatten()
array([ 0,  2,  4,  6,  8, 10, 12, 14])

Dans vos propres implémentations, vous êtes libre d'ignorer le contrat mentionné ci-dessus et de l'utiliser à votre guise.

Torsten Marek
la source
Peut-être que je me trompe mais n'est-ce pas cela qui a[:,:,:,0]renverra une copie et a[...,0]renverra la "vue" et non la copie? J'ai essayé de courir id()contre les deux versions et pour un tableau à 3 dimensions: a[:,:,:, 0], a[:,:,:, 1], a[:,:,:, 2] tous ont des identifiants différents alors que: a[..., 0], a[..., 1], a[..., 2] tous ont les mêmes identifiants.
mohitsharma44
@ mohitsharma44 pas sur ma machine;) id()renvoie la même valeur pour les deux. Vérifier également avec __array_interface__['data']montre la même adresse mémoire.
BoltzmannBrain
Je trouve que nous pouvons même utiliser a[indexes, ...]un tableau à 1 dimension!
acgtyrant
1
Les ellipses sont également utiles pour les structures de données de dimension zéro. C'est le seul moyen que je connaisse pour écrire dans numpy.ndarrays scalaires, par exemple: my_scalar = np.asarray (3); my_scalar [...] = 5. Si vous faites my_scalar [:] = 5, vous obtiendrez à juste titre une erreur, car il n'y a pas de dimension 0 pour le: à parcourir.
SuperElectric
1
@SuperElectric Vous pouvez également utiliser my_scalar.itemset (scalarvalue). Bien sûr, my_scalar [...] = scalar_value est plus court, mais vous avez dit dans le commentaire ci-dessus, que c'est la seule façon dont vous savez. Donner juste une alternative.
kamathln
70

C'est une autre utilisation d'Ellipsis, qui n'a rien à voir avec les tranches: je l'utilise souvent dans la communication intra-thread avec les files d'attente, comme une marque qui signale "Terminé"; c'est là, c'est un objet, c'est un singleton, et son nom signifie «manque de», et ce n'est pas le None surutilisé (qui pourrait être mis dans une file d'attente dans le cadre d'un flux de données normal). YMMV.

tzot
la source
14
Ne serait-il pas plus clair de simplement dire: "Done = object ()" quelque part et de simplement l'utiliser?
Brandon Rhodes
12
Pas nécessairement - cela vous oblige à dire effectivement Done = object () quelque part. Les valeurs sentinelles ne sont pas nécessairement une mauvaise chose - et utiliser des singletons Python autrement presque inutiles comme sentinelles n'est pas si horrible IMO (Ellipsis et () sont ceux que j'ai utilisés là où None serait déroutant).
Rick Copeland
6
En ce qui concerne Done = object (), je pense qu'il est préférable d'utiliser Ellipsis, surtout si vous l'utilisez pour la communication avec les files d'attente. Si vous passez de la communication intra-thread à intra-processus, id (Done) ne sera pas le même dans l'autre processus, et il n'y a rien pour distinguer un objet d'un autre. L'identifiant d'Ellipsis ne sera pas non plus le même, mais au moins le type sera le même - c'est le point d'un singleton.
Tristan Reid
La question dit «Comment utilisez-vous les points de suspension», mais je crois que vous avez mal interprété cela. Il a de nombreuses interprétations. Mais je pense que la bonne réponse est: "Comment utilise-t-on Ellipsis?" c'est-à-dire "Quelles étapes dois-je prendre pour utiliser Ellipse dans mon propre code.".
Lyndon White
6

Comme indiqué dans d'autres réponses, il peut être utilisé pour créer des tranches. Utile lorsque vous ne souhaitez pas écrire de nombreuses notations de tranches complètes ( :), ou lorsque vous n'êtes pas sûr de la dimensionnalité du tableau manipulé.

Ce que je pensais important de souligner, et qui manquait dans les autres réponses, c'est qu'il peut être utilisé même lorsqu'il n'y a plus de dimensions à remplir.

Exemple:

>>> from numpy import arange
>>> a = arange(4).reshape(2,2)

Cela entraînera une erreur:

>>> a[:,0,:]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: too many indices for array

Cela fonctionnera:

a[...,0,:]
array([0, 1])
Mauricio Perez
la source