¿Qué hace el objeto Python Ellipsis?

Mientras navegaba ociosamente por el espacio de nombres, noté un objeto de aspecto extraño llamado ” Ellipsis “, no parece ser ni hacer nada especial, pero es un componente integrado disponible a nivel mundial.

Después de una búsqueda, descubrí que Numpy y Scipy lo utilizan en alguna variante oscura de la syntax de corte … pero casi nada más.

¿Se agregó este objeto al lenguaje específicamente para admitir Numpy + Scipy? ¿Ellipsis tiene algún significado o uso genérico?

D:\workspace\numpy>python Python 2.4.4 (#71, Oct 18 2006, 08:34:43) [MSC v.1310 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> Ellipsis Ellipsis 

    Esto surgió en otra pregunta recientemente. Voy a elaborar mi respuesta desde allí:

    Elipsis es un objeto que puede aparecer en notación de corte. Por ejemplo:

     myList[1:2, ..., 0] 

    Su interpretación depende únicamente de lo que implemente la función __getitem__ y vea los objetos Ellipsis allí, pero su uso principal (y previsto) está en la extensión numérica de Python , que agrega un tipo de matriz multidimensional. Dado que hay más de una dimensión, la segmentación se vuelve más compleja que solo un índice de inicio y detención; Es útil poder cortar también en múltiples dimensiones. Por ejemplo, dada una matriz de 4×4, el área superior izquierda se definiría mediante la división [:2,:2] :

     >>> a array([[ 1, 2, 3, 4], [ 5, 6, 7, 8], [ 9, 10, 11, 12], [13, 14, 15, 16]]) >>> a[:2,:2] # top left array([[1, 2], [5, 6]]) 

    Extendiendo esto, Ellipsis se usa aquí para indicar un marcador de posición para el rest de las dimensiones de la matriz no especificadas. Piense en ello como que indica la división completa [:] para todas las dimensiones en el espacio que se coloca, por lo que para una matriz 3d, a[...,0] es lo mismo que a[:,:,0] y para 4d, a[:,:,:,0] , de manera similar, a[0,...,0] es a[0,:,:,0] (con muchos colones en el medio, forman el número completo de dimensiones en la matriz).

    Curiosamente, en python3, el literal de Ellipsis ( ... ) se puede usar fuera de la syntax de la porción, por lo que realmente puede escribir:

     >>> ... Ellipsis 

    Aparte de los diversos tipos numéricos, no, no creo que se use. Por lo que yo sé, se agregó únicamente para uso numérico y no tiene ningún soporte central que no sea proporcionar el objeto y la syntax correspondiente. El objeto que estaba allí no requería esto, pero el soporte literal “…” para los cortes lo hizo.

    En Python 3, puedes usar el literal de Ellipsis ... como un marcador de posición “nop” para el código:

     def will_do_something(): ... 

    Esto no es magia; Se puede utilizar cualquier expresión en lugar de ... , por ejemplo:

     def will_do_something(): 1 

    (No puedo usar la palabra “sancionado”, pero puedo decir que Guido no rechazó de plano este uso).

    También puede utilizar la elipsis al especificar el resultado de doctest esperado:

     class MyClass(object): """Example of a doctest Ellipsis >>> thing = MyClass() >>> # Match  and  >>> type(thing) # doctest:+ELLIPSIS  """ pass 

    A partir de Python 3.5 y PEP484 , los puntos suspensivos literales se usan para denotar ciertos tipos a un verificador de tipos estático cuando se usa el módulo de escritura .

    Ejemplo 1:

    Las tuplas homogéneas de longitud arbitraria se pueden express utilizando un tipo y puntos suspensivos, por ejemplo Tuple[int, ...]

    Ejemplo 2:

    Es posible declarar el tipo de retorno de un llamable sin especificar la firma de la llamada sustituyendo un punto suspensivo literal (tres puntos) para la lista de argumentos:

     def partial(func: Callable[..., str], *args) -> Callable[..., str]: # Body 

    De la documentación de Python :

    Este objeto es usado por la notación de división extendida (consulte el Manual de referencia de Python ). No soporta operaciones especiales. Hay exactamente un objeto de puntos suspensivos, denominado Ellipsis (un nombre incorporado).

    Resumiendo lo que otros han dicho, a partir de Python 3, Ellipsis es esencialmente otra constante de singleton similar a None , pero sin un uso específico en particular. Los usos existentes incluyen:

    • En la syntax de división para representar la división completa en las dimensiones restantes
    • En la indicación de tipo para indicar solo una parte de un tipo ( Callable[..., int] o Tuple[str, ...] )
    • En archivos de código auxiliar de tipo para indicar que hay un valor predeterminado sin especificarlo

    Los posibles usos podrían incluir:

    • Como valor predeterminado para lugares donde None es una opción válida
    • Como el contenido de una función que aún no has implementado.

    Puede usar Ellipsis usted mismo, en situaciones de corte personalizadas como ha hecho numpy, pero no tiene uso en ninguna clase incorporada.

    No sé si se agregó específicamente para su uso en números, pero ciertamente no lo he visto en ningún otro lugar.

    Ver también: ¿Cómo se usa la syntax de división de puntos suspensivos en Python?

    __getitem__ minimal ... ejemplo en una clase personalizada

    Cuando la syntax mágica ... pasa a [] en una clase personalizada, __getitem__() recibe un objeto de clase Ellipsis .

    La clase puede hacer lo que quiera con este objeto Singleton.

    Ejemplo:

     class C(object): def __getitem__(self, k): return k # Single argument is passed directly. assert C()[0] == 0 # Multiple indices generate a tuple. assert C()[0, 1] == (0, 1) # Slice notation generates a slice object. assert C()[1:2:3] == slice(1, 2, 3) # Ellipsis notation generates the Ellipsis class object. # Ellipsis is a singleton, so we can compare with `is`. assert C()[...] is Ellipsis # Everything mixed up. assert C()[1, 2:3:4, ..., 6] == (1, slice(2,3,4), Ellipsis, 6) 

    La clase de list incorporada de Python elige darle la semántica de un rango, y cualquier uso sensato de la misma debería, por supuesto, también.

    Personalmente, me mantendría alejado de él en mis API y, en su lugar, crearía un método separado y más explícito.

    Probado en Python 3.5.2 y 2.7.12.

    Su uso previsto no debe ser solo para estos módulos de terceros. No se menciona correctamente en la documentación de Python (o tal vez simplemente no pude encontrarlo) pero los puntos suspensivos ... realidad se usan en CPython en al menos un lugar.

    Se utiliza para representar estructuras de datos infinitas en Python. Me encontré con esta notación jugando con listas.

    Vea esta pregunta para más información.

    Como lo mencionaron @noɥʇʎԀʎzɐɹƆ y @phoenix – De hecho, puede usarlo en archivos de código auxiliar. p.ej

    class Foo: bar: Any = ... def __init__(self, name: str=...) -> None: ...

    Puede encontrar más información y ejemplos de cómo utilizar estos puntos suspensivos aquí https://www.python.org/dev/peps/pep-0484/#stub-files