2009-04-21 23 views
300

Mientras navegaba ociosamente en el espacio de nombres noté un objeto de aspecto extraño llamado "Ellipsis", no parece ser ni hace nada especial, pero es una construcción interna disponible en todo el mundo.¿Qué hace el objeto Python Ellipsis?

Después de una búsqueda encontré que se usa en algunas variantes oscuras de la sintaxis de corte por Numpy y Scipy ... pero casi nada más.

¿Se ha agregado este objeto al idioma específicamente para admitir Numpy + Scipy? Ellipsis tiene algún significado genérico o uso en absoluto?

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

Ver las respuestas a http://stackoverflow.com/questions/752602/slicing-in-python-expressions -documentación –

+5

Lo encontré así: escribí 'x = []; x.append (x); print (x)', para ver cómo manejaba la stringificación de objetos cíclicos. Devolvió '[[...]]'. Pensé: "Me pregunto qué sucederá si escribo' [[...]] 'Supongo que arrojaría un error de sintaxis. En su lugar, devolvió' [[Ellipsis]] '. Python es tan extraño. la búsqueda que siguió me llevó a esta página. – Cyoce

+9

tenga en cuenta que el '...' en una representación recursiva es solo un marcador de posición y no tiene relación con 'Ellipsis' – Eevee

Respuesta

350

Esto apareció en otro question recientemente. Elaboraré en mi answer desde allí:

Ellipsis es un objeto que puede aparecer en la notación de división. Por ejemplo:

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

Su interpretación es puramente hasta lo implementa la función __getitem__ y ve Ellipsis objetos allí, pero su principal (y la intención) es el uso de la extensión numeric python, lo que añade un tipo de matriz multidimensional. Como hay más de una dimensión, cortar se vuelve más complejo que solo un índice de inicio y finalización; también es útil para cortar en varias dimensiones. Por ejemplo, dada una matriz de 4x4, la zona superior izquierda se definiría por la rebanada [: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]]) 

La extensión de este más allá, Ellipsis se utiliza aquí para indicar un marcador de posición para el resto de las dimensiones de la matriz no especificados. Piense en ello como indicando el corte completo [:] para todas las dimensiones en el espacio en el que está colocado, por lo que para un arreglo 3D, a[...,0] es lo mismo que a[:,:,0] y para 4d, a[:,:,:,0], del mismo modo, a[0,...,0] es a[0,:,:,0] (con tantos puntos en el el medio compone el número completo de dimensiones en la matriz).

Curiosamente, en python3, los puntos suspensivos literal (...) se puede utilizar fuera de la sintaxis de corte, por lo que en realidad se puede escribir:

>>> ... 
Ellipsis 

Aparte de los diversos tipos numéricos, no, no creo que es usado.Por lo que yo sé, fue agregado exclusivamente para uso numpy y no tiene ningún soporte básico que no sea proporcionar el objeto y la sintaxis correspondiente. El objeto que estaba allí no lo requería, pero el soporte literal "..." sí lo requería.

+12

Bah humbug. Estás usando' Ellipsis' equivocado. Claramente se supone que debes usarlo así: 'a [Ellipsis, 0]', nada de esto tonto '...'. – ArtOfWarfare

+6

es también utilizado en el tipo de pista PEP484 en archivos de código auxiliar –

9

Puede utilizar puntos suspensivos a sí mismo, en situaciones de rebanado personalizados como numpy ha hecho, pero no tiene ningún uso en cualquier clase incorporado.

No sé si se ha agregado específicamente para su uso en numpy, pero ciertamente no lo he visto en otro lugar.

Consulte también: How do you use the ellipsis slicing syntax in Python?

29

Desde el Python documentation:

Este objeto se utiliza la notación extendida por rebanada (ver la Python Reference Manual). No admite operaciones especiales . Hay exactamente un objeto ellipsis , llamado Ellipsis (un nombre incorporado ).

109

En Python 3, puede utilizar los puntos suspensivos literal ... como un marcador de posición “nop” para el código:

def will_do_something(): 
    ... 

Ésta es no magia; cualquier expresión se puede utilizar en lugar de ..., por ejemplo:

def will_do_something(): 
    1 

(. No se puede utilizar la palabra “sancionado”, pero puedo decir que este uso fue not outrightly rejected por Guido)

+105

En una semi-convención, a menudo veo '' ... '' usado donde la gente quiere indicar algo que pretenden completar más tarde (un bloque vacío 'todo') y '' pase '' para significar un bloque destinado a no tener código. –

+11

Python también tiene el literal 'NotImplemented', que es útil cuando desee que su función incompleta devuelva algo significativo (en lugar de 'None' como en su ejemplo). (Otro uso: [Implementando operaciones aritméticas] (https://docs.python.org/3/library/numbers.html#implementing-the-arithmetic-operations)) – zvyn

+7

@zvyn Eso no es literal. Es solo un nombre. Por ejemplo 'NotImplemented = 'something_else'' es válido python, pero' ... =' something_else'' es un error de sintaxis. – wim

37

También puede utilizar los puntos suspensivos al especificar espera doctest de salida:

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

¿Pero esto realmente involucra el objeto Ellipsis? ¿No es solo una característica del doctest parser/matcher? – akaihola

+0

@akaihola Yo diría que sí, como se describe en [doctest.ELLIPSIS] (https://docs.python.org/2/library/doctest.html#doctest.ELLIPSIS). Espero que la mayoría, si no todos, los usos de '...' son sintácticos, y no 'usan' el objeto Ellipsis real. ¿No es realmente nada más que un nombre práctico para un concepto adaptable? – nealmcb

0

Su uso pretendido no debe ser sólo para estos módulos de 3 ª parte. No se menciona correctamente en la documentación de Python (o tal vez no pude encontrarlo) pero el elipse ... se usa realmente en CPython en al menos un lugar.

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

Consulte this question para obtener más información.

+7

Diferentes cosas. Esta pregunta se refiere al tipo integrado 'elipsis' y al objeto' Ellipsis'. La representación de estructuras de datos infinitas con elipses es puramente para mostrar, sin tener nada que ver con el tipo de "puntos suspensivos" o el objeto "Elipsis". – chys

+2

@chys En realidad, lo hace de una manera pequeña: las cadenas Python '__repr__' apuntan a ser expresiones de Python válidas. Si no fuera por ellipsis existente en el lenguaje como lo hace, la representación no sería una expresión válida. –

+2

@Lattyware Bueno, es cierto que el diseño original así lo pretende. También pretende que 'eval (repr (a))' apunte a ser igual a 'a'. Desafortunadamente es falso de vez en cuando en la práctica, incluso para los tipos integrados. Pruebe esto: 'a = []; a.append (a); eval (repr (a)) '. 'repr (a)' es '[[...]]', expresión inválida en Python 2. (En Python 3 es válido, pero el resultado de evaluación es algo diferente, aún contrario a la intención original). – chys

3

__getitem__ ejemplos mínimos

sirve como valor de la magia clase singleton que se pasa a __getitem__ cuando se utiliza la sintaxis ... "magia de aspecto".

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 an Ellipsis class object. 
assert C()[...] == Ellipsis 

El Python incorporado list clase elige para darle la semántica de un intervalo, y cualquier uso cuerdo de lo que debería también, por supuesto.

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

24

A partir de Python 3.5 y PEP484, la elipsis literal se utiliza para denotar ciertos tipos a un verificador de tipo estático cuando se utiliza el módulo typing.

Ejemplo 1:

-longitud arbitraria tuplas homogéneos pueden ser expresados ​​usando un tipo y puntos suspensivos, por ejemplo Tuple[int, ...]

Ejemplo 2:

Es posible declarar el tipo de devolución de un invocable sin especificar la firma de llamada sustituyendo una elipsis literal (tres puntos) por la lista de argumentos:

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

como se ha mencionado por @ noɥʇʎԀʎzɐɹƆ y @phoenix - Efectivamente, puedes utilizarlo en archivos de marcadores. p.ej.

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

Más información y ejemplos de cómo utilizar esta elipse se pueden descubrir aquí https://www.python.org/dev/peps/pep-0484/#stub-files