¿Cómo se usa la sintaxis de corte de puntos suspensivos en Python?

Respuestas:

102

Ellipsiso ...no es una característica oculta, es solo una constante. Es bastante diferente a, digamos, javascript ES6, donde forma parte de la sintaxis del lenguaje. Ninguna clase incorporada o construcción de lenguaje Python hace uso de ella.

Entonces, la sintaxis para ello depende completamente de que usted o alguien más tenga un código escrito para comprenderlo.

Numpy lo usa, como se indica en la documentación . Algunos ejemplos aquí .

En tu propia clase, lo usarías así:

>>> 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

Por supuesto, está la documentación de Python y la referencia del lenguaje . Pero esos no son muy útiles.

nosklo
fuente
66
parece bastante roto ya que la forma "adecuada" de decir todos los elementos es >>> x [:] >>> x [:, 1: 2]
Ronny
30
@Ronny: El objetivo era demostrar un uso personalizado de puntos suspensivos.
nosklo
77
Los enlaces parecen estar rotos.
SwiftsNamesake
231

La elipsis se utiliza en numpy para cortar estructuras de datos de dimensiones superiores.

Está diseñado para significar en este punto, inserte tantos cortes completos ( :) para extender el corte multidimensional a todas las dimensiones .

Ejemplo :

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

Ahora, tiene una matriz de 4 dimensiones de orden 2x2x2x2. Para seleccionar todos los primeros elementos en la cuarta dimensión, puede usar la notación de puntos suspensivos

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

que es equivalente a

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

En sus propias implementaciones, puede ignorar el contrato mencionado anteriormente y utilizarlo para lo que considere conveniente.

Torsten Marek
fuente
Tal vez estoy equivocado, pero ¿no es eso lo que a[:,:,:,0]devolverá una copia y a[...,0]devolverá la "vista" y no la copia? Intenté ejecutar id()contra ambas versiones y para una matriz de 3 dim: a[:,:,:, 0], a[:,:,:, 1], a[:,:,:, 2] todos tienen diferentes identificadores, mientras que: a[..., 0], a[..., 1], a[..., 2] todos tienen los mismos identificadores.
mohitsharma44
@ mohitsharma44 no está en mi máquina;) id()devuelve el mismo valor para ambos. Verificando también __array_interface__['data']muestra la misma dirección de memoria.
BoltzmannBrain
¡Creo que podemos usar a[indexes, ...]mientras que a es una matriz de 1 dimensión incluso!
acgtyrant
1
Las elipses también son útiles para estructuras de datos de dimensión cero. Son la única forma que conozco para escribir en escalar numpy.ndarrays, por ejemplo: my_scalar = np.asarray (3); my_scalar [...] = 5. Si haces my_scalar [:] = 5, legítimamente obtendrás un error, porque no hay una dimensión 0 para: iterar.
SuperElectric
1
@SuperElectric También puede usar my_scalar.itemset (scalarvalue). Por supuesto, my_scalar [...] = scalar_value es más corto, pero usted dijo en el comentario anterior, que es la única forma de saberlo. Solo dando una alternativa.
kamathln
70

Este es otro uso para Ellipsis, que no tiene nada que ver con cortes: a menudo lo uso en comunicación intra-hilo con colas, como una marca que indica "Hecho"; está allí, es un objeto, es un singleton, y su nombre significa "falta de", y no es el None usado en exceso (que podría ponerse en una cola como parte del flujo de datos normal). YMMV.

tzot
fuente
14
¿No sería más claro decir: "Listo = objeto ()" en alguna parte y simplemente usar eso?
Brandon Rhodes el
12
No necesariamente: requiere que digas Done = object () en alguna parte. Los valores de centinela no son necesariamente algo malo, y el uso de singletons de Python casi inútiles como centinelas no es tan horrible IMO (puntos suspensivos y () son los que he usado donde Ninguno sería confuso).
Rick Copeland
66
Con respecto a Done = object (), creo que usar Ellipsis es mejor, especialmente si lo está usando para comunicarse con colas. Si pasa de la comunicación entre subprocesos a dentro del proceso, el id (Listo) no será el mismo en el otro proceso, y no hay nada que distinga un objeto de otro. El id de Ellipsis tampoco será el mismo, pero al menos el tipo será el mismo: este es el punto de un singleton.
Tristan Reid el
La pregunta dice "¿Cómo usas los puntos suspensivos?", Pero creo que lo tomaste mal. Tiene muchas interpretaciones. Pero creo que lo correcto es: "¿Cómo se usa la elipsis?" es decir, "¿Qué pasos debo seguir para utilizar Elipsis en mi propio código?".
Lyndon White
6

Como se indicó en otras respuestas, se puede usar para crear sectores. Útil cuando no desea escribir muchas anotaciones de cortes completos ( :), o cuando no está seguro de cuál es la dimensionalidad de la matriz que se está manipulando.

Lo que me pareció importante destacar, y que faltaba en las otras respuestas, es que se puede usar incluso cuando no hay más dimensiones que llenar.

Ejemplo:

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

Esto dará como resultado un error:

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

Esto funcionará:

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