182 votes

Comment utiliser la syntaxe de découpage en ellipses en Python ?

C'est apparu dans Fonctions cachées de Python mais je ne vois pas de bonne documentation ou d'exemples qui expliquent le fonctionnement de cette fonctionnalité.

278voto

Torsten Marek Points 27554

L'ellipse est utilisée dans numpy pour découper les structures de données à haute dimension.

Il est conçu pour signifier à ce stade, insérez 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 dans la 4e dimension, vous pouvez utiliser la notation de l'ellipse

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

ce qui est équivalent à

>>> 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 comme bon vous semble.

1 votes

Peut-être que je me trompe mais n'est-ce pas que a[:,:,:,0] retournera une copie et a[...,0] retournera la "vue" et non la copie ? J'ai essayé d'exécuter id() contre les deux versions et pour un tableau 3-dim : a[:,:,:, 0], a[:,:,:, 1], a[:,:,:, 2] tous ont des identifiants différents alors que : a[..., 0], a[..., 1], a[..., 2] ont tous le même identifiant.

0 votes

@mohitsharma44 pas sur ma machine ;) id() renvoie la même valeur pour les deux. Il faut également vérifier avec __array_interface__['data'] montre la même adresse mémoire.

0 votes

Je trouve que nous pouvons utiliser a[indexes, ...] alors que a est un tableau 1-dimenstionnel même !

116voto

nosklo Points 75862

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

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

Numpy l'utilise, comme indiqué dans le 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 le documentation python et référence linguistique . Mais ils ne sont pas très utiles.

7 votes

Semble assez cassé puisque la façon "prope" de dire tous les éléments est >>> x[ :] >>> x[ :, 1:2]

34 votes

@Ronny : Le but était de démontrer une utilisation personnalisée d'Ellipsis.

8 votes

Les liens semblent être rompus.

70voto

tzot Points 32224

C'est une autre utilisation de l'ellipse, 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 "Done" ; il est là, c'est un objet, c'est un singleton, et son nom signifie "absence de", et ce n'est pas le None surutilisé (qui pourrait être mis dans une file d'attente dans le cadre du flux de données normal). YMMV.

15 votes

Ne serait-il pas plus clair de dire simplement : "Done = object()" quelque part et de l'utiliser comme ça ?

12 votes

Pas nécessairement - cela nécessite que vous fassiez dites Done=object() quelque part. Les valeurs sentinelles ne sont pas nécessairement une mauvaise chose -- et utiliser des singletons Python presque inutiles comme sentinelles n'est pas si horrible IMO (Ellipsis et () sont ceux que j'ai utilisés là où None serait confus).

6 votes

En ce qui concerne Done = object(), je pense qu'il vaut mieux utiliser Ellipsis, surtout si vous l'utilisez pour communiquer avec des files d'attente. Si vous passez d'une communication intra-thread à une communication 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'id d'Ellipsis ne sera pas le même non plus, mais au moins le type sera le même - c'est l'intérêt d'un singleton.

10voto

Mauricio Perez Points 81

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

Ce qui me semblait 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

Ça va marcher :

a[...,0,:]
array([0, 1])

-2voto

Aseem Bansal Points 1369

La documentation de Python n'est pas très claire à ce sujet, mais il existe une autre utilisation de l'ellipse. Elle est utilisée comme représentation de structures de données infinies dans le cas de Python. Cette question discute du comment et de quelques applications réelles.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X