Cosa fa l'oggetto Ellisse?


540

Mentre navigavo pigramente nello spazio dei nomi, ho notato un oggetto dall'aspetto strano chiamato Ellipsis, non sembra essere o fare qualcosa di speciale, ma è un builtin disponibile a livello globale.

Dopo una ricerca ho scoperto che è usato in qualche oscura variante della sintassi di taglio di Numpy e Scipy ... ma quasi nient'altro.

Questo oggetto è stato aggiunto alla lingua appositamente per supportare Numpy + Scipy? L'ellissi ha un significato o un uso generico?

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


19
L'ho trovato in questo modo: sono entrato x=[];x.append(x);print(x), per vedere come gestiva il stringing di oggetti ciclici. È tornato [[...]]. Ho pensato "Mi chiedo cosa succede se digito [[...]]? Immagino che avrebbe generato un errore di sintassi. Invece, è tornato [[Ellipsis]]. Python è così strano. La ricerca su Google che ne è seguita mi ha portato a questa pagina.
Cyoce

22
nota che ...in una repr ricorsiva è solo un segnaposto e non ha alcuna relazione conEllipsis
Eevee,

16
In una nota totalmente a parte, il punto triplo in import significa "import da due pacchetti in su".
Fisico pazzo,

1
@croq stackoverflow.com/q/32395926/2988730 . stackoverflow.com/q/1054271/2988730 . Quei due dovrebbero spiegare tutto, con collegamenti adeguati a documenti e PEP nelle risposte.
Fisico pazzo,

Risposte:


559

Questo è emerso in un'altra domanda di recente. Elaborerò la mia risposta da lì:

L'ellissi è un oggetto che può apparire in notazione di sezioni. Per esempio:

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

La sua interpretazione dipende esclusivamente da ciò che implementa la __getitem__funzione e vede gli Ellipsisoggetti lì, ma il suo uso principale (e previsto) è nella biblioteca di terze parti intorpidita , che aggiunge un tipo di array multidimensionale. Poiché esistono più dimensioni, la suddivisione diventa più complessa di un semplice indice di inizio e fine; è utile poter tagliare anche in più dimensioni. Ad esempio, dato un array 4x4, l'area in alto a sinistra sarebbe definita dalla sezione [: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]])

Estendendolo ulteriormente, Ellipsis viene utilizzato qui per indicare un segnaposto per il resto delle dimensioni dell'array non specificate. Pensalo come se indicasse la sezione intera [:]per tutte le dimensioni nello spazio in cui è posizionata, quindi per un array 3d, a[...,0]è lo stesso di a[:,:,0]e per 4d a[:,:,:,0], allo stesso modo, a[0,...,0]è a[0,:,:,0](con comunque molti punti al centro compongono il numero intero di dimensioni nella matrice).

È interessante notare che in python3, l'Ellipsis literal ( ...) è utilizzabile al di fuori della sintassi della sezione, quindi puoi effettivamente scrivere:

>>> ...
Ellipsis

A parte i vari tipi numerici, no, non penso che sia usato. Per quanto ne so, è stato aggiunto esclusivamente per un uso intorpidito e non ha supporto di base se non quello di fornire l'oggetto e la sintassi corrispondente. L'oggetto lì non lo richiedeva, ma il supporto letterale "..." per gli slice lo faceva.


22
è anche usato nel tipo di suggerimento PEP484 nei file stub
noɥʇʎԀʎzɐɹƆ

24
Nel caso qualcuno fosse curioso: è anche usato nel typingmodulo libreria standard: ad es. Callable[..., int]Per indicare un callable che restituisce un intsenza specificare la firma o Tuple[str, ...]per indicare una tupla omogenea di stringhe di lunghezza variabile.
Anakhand,

6
Cordiali saluti, anche il framework FastAPI (che è per Python 3.6+) lo usa (ora). fastapi.tiangolo.com/tutorial/query-params-str-validations
Andrew Allaire

2
@ArtOfWarfare hai perfettamente ragione, e questo proviene da qualcuno che dice verbalmente "ellissi" invece di finire tra le frasi.
PrimeRibeyeDeal

Ho trovato questo. Sembra apparire quando si fa un auto-riferimento (riferimento circolare) in un elenco: a = [1, 2]; a[0] = a; print(a)[[...], 2]. È la stessa cosa o un uso diverso?
Bill

220

In Python 3, puoi usare il letterale Ellipsis ...come segnaposto "nop" per il codice:

def will_do_something():
    ...

Questa non è magia; è possibile utilizzare qualsiasi espressione anziché ..., ad esempio:

def will_do_something():
    1

(Non posso usare la parola "sanzionato", ma posso dire che questo uso non è stato apertamente respinto da Guido.)


181
In una mezza convenzione, vedo spesso ...usato dove le persone vogliono indicare qualcosa che intendono riempire in seguito (un blocco vuoto 'todo') e passintendere un blocco destinato a non avere codice.
Gareth Latty,

26
Python ha anche il valore NotImplementedletterale, che è utile quando vuoi che la tua funzione incompleta restituisca qualcosa di significativo (invece che Nonecome nel tuo esempio). (Un altro caso d'uso: implementazione di operazioni aritmetiche )
zvyn,

13
@zvyn Questo non è letterale. È solo un nome. Ad esempio NotImplemented = 'something_else'è valido Python, ma ... = 'something_else'è un errore di sintassi.
mercoledì

4
@zvyn Cosa succede se si verifica un'eccezione durante l'importazione di quel modulo? :)
pizzapants184

7
@zvyn NotImplementednon vuole essere un'alternativa a None. Il suo utilizzo è piuttosto limitato. Vedi la documentazione qui
hans

69

A partire da Python 3.5 e PEP484 , i puntini di sospensione letterali vengono utilizzati per indicare determinati tipi a un controllo di tipo statico quando si utilizza il modulo di digitazione .

Esempio 1:

Le tuple omogenee di lunghezza arbitraria possono essere espresse usando un tipo e ellissi, per esempio Tuple[int, ...]

Esempio 2:

È possibile dichiarare il tipo restituito di un callable senza specificare la firma della chiamata sostituendo una ellissi letterale (tre punti) per l'elenco degli argomenti:

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

46

È inoltre possibile utilizzare l'ellissi quando si specifica l' output doctest previsto :

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

9
Ma questo in realtà coinvolge l'oggetto Ellipsis? Non è solo una caratteristica del parser / matcher doctest?
Akaihola,

1
@akaihola Direi che è così, come descritto su doctest.ELLIPSIS . Mi aspetto che la maggior parte, se non tutti gli usi di, ...siano sintattici e non usel'oggetto reale di Ellissi. Non è davvero nient'altro che un nome utile per un concetto adattabile?
nealmcb,


25

Riassumendo ciò che altri hanno detto, a partire da Python 3, Ellipsis è essenzialmente un'altra costante singleton simile None, ma senza un uso previsto. Gli usi esistenti includono:

  • Nella sintassi della sezione per rappresentare l'intera sezione nelle dimensioni rimanenti
  • Nel tipo di suggerimento per indicare solo una parte di un tipo ( Callable[..., int]oTuple[str, ...] )
  • Nel tipo di file stub indicare che esiste un valore predefinito senza specificarlo

I possibili usi potrebbero includere:

  • Come valore predefinito per i luoghi in cui Noneè un'opzione valida
  • Come contenuto per una funzione che non hai ancora implementato

14

__getitem__...esempio minimo in una classe personalizzata

Quando la sintassi magica ...viene passata a []in una classe personalizzata, __getitem__()riceve un Ellipsisoggetto classe.

La classe può quindi fare quello che vuole con questo oggetto Singleton.

Esempio:

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)

Il Python integrato list classe sceglie di dargli la semantica di un intervallo, e ovviamente anche qualsiasi uso sano di essa dovrebbe essere.

Personalmente, me ne starei lontano dalle mie API e creerei invece un metodo separato, più esplicito.

Testato in Python 3.5.2 e 2.7.12.




7

Come accennato da @ noɥʇʎԀʎzɐɹƆ e @phoenix - Puoi davvero usarlo nei file stub. per esempio

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

Maggiori informazioni ed esempi su come usare questi puntini di sospensione sono disponibili qui https://www.python.org/dev/peps/pep-0484/#stub-files


2

L'uso previsto non dovrebbe essere solo per questi moduli di terze parti. Non è menzionato correttamente nella documentazione di Python (o forse non riuscivo a trovarlo) ma i puntini di sospensione ...sono effettivamente utilizzati in CPython in almeno un posto.

È usato per rappresentare infinite strutture di dati in Python. Mi sono imbattuto in questa notazione mentre giocavo con le liste.

Vedi questa domanda per maggiori informazioni.


8
Cose diverse. Questa domanda fa domande sul ellipsistipo incorporato e Ellipsissull'oggetto. La rappresentazione di infinite strutture di dati con ellissi è puramente per la visualizzazione, non avendo nulla a che fare con il ellipsistipo o l' Ellipsisoggetto.
Chys,

3
@chys In realtà, lo fa in un piccolo modo - le __repr__stringhe di Python mirano ad essere espressioni Python valide - se non fosse per le ellissi esistenti nel linguaggio, la rappresentazione non sarebbe un'espressione valida.
Gareth Latty,

3
@Lattyware Bene, è vero che il design originale intende così. Intende anche che l' eval(repr(a))obiettivo sia uguale a a. Purtroppo è falso di tanto in tanto in pratica, anche per i tipi integrati. Prova questo fuori: a=[]; a.append(a); eval(repr(a)). repr(a)è [[...]], espressione non valida in Python 2. (In Python 3 è valido, ma il risultato eval è qualcosa di diverso, ancora contrario all'intenzione originale.)
chys

1

Questo è equivalente.

l=[..., 1,2,3]
l=[Ellipsis, 1,2,3]

...è una costante definita all'interno built-in constants.

ellissi

Lo stesso dell'ellissi letterale "...". Valore speciale utilizzato principalmente in combinazione con la sintassi di suddivisione estesa per tipi di dati contenitore definiti dall'utente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.