¿Qué hace el objeto Python Ellipsis?
(10)
A partir de Python 3.5 y PEP484 , los puntos suspensivos literales se usan para denotar ciertos tipos a un verificador de tipo estático cuando se usa el módulo de typing .
Ejemplo 1:
Las tuplas homogéneas de longitud arbitraria se pueden expresar 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
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 utilizan una variante oscura de la sintaxis 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
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
De la documentación de Python :
Este objeto es usado por 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).
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).
Esto surgió en otra question recientemente. Voy a elaborar mi answer desde allí:
Ellipsis 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 dividir en múltiples dimensiones también. Por ejemplo, dada una matriz de 4x4, 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 resto 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 sintaxis 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 soporte central más que proporcionar el objeto y la sintaxis correspondiente. El objeto que estaba allí no requería esto, pero el soporte literal "..." para los cortes lo hizo.
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 sintaxis de división de puntos suspensivos en Python?
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 sintaxis de división para representar la división completa en las dimensiones restantes
- En la sugerencia de tipo para indicar solo parte de un tipo (
Callable[..., int]
oTuple[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 los lugares donde
None
es una opción válida - Como el contenido de una función que aún no has implementado.
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.
También puede utilizar la elipsis cuando especifique doctest resultado doctest esperado:
class MyClass(object):
"""Example of a doctest Ellipsis
>>> thing = MyClass()
>>> # Match <class ''__main__.MyClass''> and <class ''%(module).MyClass''>
>>> type(thing) # doctest:+ELLIPSIS
<class ''....MyClass''>
"""
pass
__getitem__
minimal ...
ejemplo en una clase personalizada
...
sirve como un valor mágico de clase singleton que se pasa a __getitem__
cuando usas la sintaxis "mágica" ...
La clase puede hacer lo que quiera con ella.
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.