2009-04-21 30 views
300

Mentre navigavo nel namespace ho notato un oggetto dall'aspetto strano chiamato "Ellipsis", non sembra essere o fare nulla di speciale, ma è un built-in globalmente disponibile.Cosa fa l'oggetto Python Ellipsis?

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

Questo oggetto è stato aggiunto alla lingua specificamente 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 
+0

vedere le risposte a http://stackoverflow.com/questions/752602/slicing-in-python-expressions -documentation –

+5

L'ho trovato in questo modo: Ho inserito 'x = []; x.append (x); print (x)', per vedere come ha gestito l'ottimizzazione degli oggetti ciclici. Ha restituito '[[...]]'. Ho pensato "Mi chiedo cosa succede se digito in [[...]]' La mia ipotesi era che avrebbe generato un errore di sintassi, invece restituito '[[Ellipsis]]." Python è così strano. la ricerca che seguì mi portò a questa pagina. – Cyoce

+9

nota che il '...' in un repr ricorsivo è solo un segnaposto e non ha alcuna relazione con 'Ellipsis' – Eevee

risposta

350

Questo è venuto in un altro question di recente. Elaborerò il mio numero da

Ellipsis è un oggetto che può essere visualizzato nella notazione di sezione. Ad esempio:

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

L'interpretazione è puramente fino a qualsiasi implementa la funzione __getitem__ e vede Ellipsis oggetti lì, ma la sua principale (e destinati) utilizzo è in numeric python estensione, che aggiunge un tipo array multidimensionale. Poiché esistono più dimensioni, l'affettatura diventa più complessa di un semplice indice di inizio e fine; è utile poter tagliare anche più dimensioni. Ad esempio, data una matrice 4x4, nell'area superiore sinistra sarebbe definito dalla fetta [: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]]) 

Estendendo ulteriormente questo aspetto, ellissi è qui utilizzato per indicare un segnaposto per il resto delle dimensioni di matrice non specificati. Pensa ad esso come ad indicare la fetta intera [:] per tutte le dimensioni dello spazio vuoto, 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 due punti nel medio compone il numero completo di dimensioni nell'array).

È interessante notare che, nel python3, l'ellissi letterale (...) è utilizzabile al di fuori la sintassi slice, in modo da poter effettivamente scrivere:

>>> ... 
Ellipsis 

Oltre ai vari tipi numerici, no, non credo che sia Usato.Per quanto ne so, è stato aggiunto esclusivamente per uso di Numpy e non ha alcun supporto di base oltre a fornire l'oggetto e la sintassi corrispondente. L'oggetto presente non lo richiedeva, ma il letterale "..." supporto per le fette lo faceva.

+12

Bah humbug. Stai usando' Ellipsis' sbagliato. Ovviamente dovresti usarlo in questo modo: 'a [Ellipsis, 0]', nessuno di questi stupidi '...'. – ArtOfWarfare

+6

è anche usato nel tipo di suggerimento PEP484 nei file stub –

9

È possibile utilizzare Ellipsis te stesso, in situazioni di affettamento personalizzati come NumPy ha fatto, ma non ha alcun utilizzo in qualsiasi classe incorporato.

Non so se è stato aggiunto specificamente per l'uso in numpy, ma certamente non l'ho visto usato altrove.

Consulta anche: How do you use the ellipsis slicing syntax in Python?

29

Dal Python documentation:

Questo oggetto viene utilizzato per esteso fetta notazione (vedi Python Reference Manual). Non supporta operazioni speciali . Esiste esattamente un oggetto di ellissi , denominato Ellipsis (un nome incorporato ).

109

In Python 3, è possibile utilizzare l'Ellipsis letterale ... come segnaposto “NOP” per il codice:

def will_do_something(): 
    ... 

Questo è non magia; qualsiasi espressione può essere usato al posto di ..., ad esempio:

def will_do_something(): 
    1 

(. Non è possibile usare la parola “sanzionato”, ma posso dire che questo uso è stato not outrightly rejected da Guido)

+105

In mezzo-convenzione, vedo spesso '' ... '' usato dove le persone vogliono indicare qualcosa che intendono riempire in seguito (un blocco 'todo' vuoto) e '' passare '' per indicare un blocco che non ha codice. –

+11

Python ha anche il valore letterale 'NotImplemented', che è utile quando vuoi che la tua funzione incompleta restituisca qualcosa di significativo (invece di 'None' come nel tuo esempio). (Un altro caso: [Implementare operazioni aritmetiche] (https://docs.python.org/3/library/numbers.html#implementing-the-arithmetic-operations)) – zvyn

+7

@zvyn Questo non è un valore letterale. È solo un nome. Ad esempio, 'NotImplemented = 'something_else'' è python valido, ma' ... =' something_else'' è un errore di sintassi. – wim

37

È inoltre possibile utilizzare i puntini di sospensione quando si specifica prevede doctest uscita:

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

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

+0

@akaihola Direi che lo fa, come descritto in [doctest.ELLIPSIS] (https://docs.python.org/2/library/doctest.html#doctest.ELLIPSIS). Mi aspetto che la maggior parte se non tutti gli usi di '...' siano sintattici, e non 'usino' l'oggetto Ellipsis attuale. Non è davvero nient'altro che un nome pratico per un concetto adattabile? – nealmcb

0

alla destinazione d'uso non deve essere solo per questi moduli 3rd party. Non è menzionato correttamente nella documentazione di Python (o forse non lo trovo proprio) ma i puntini di sospensione ... vengono effettivamente utilizzati in CPython in almeno un punto.

Viene utilizzato per rappresentare strutture dati infinite in Python. Mi sono imbattuto in questa notazione mentre giocavo con le liste.

Vedere this question per ulteriori informazioni.

+7

Cose diverse. Questa domanda si pone in merito al tipo built-in 'ellissi 'e all'oggetto' Ellipsis'. Rappresentare strutture di dati infiniti con ellissi è puramente per la visualizzazione, non avendo nulla a che fare con il tipo 'ellissi 'o oggetto' Ellipsis'. – chys

+2

@chys In realtà, lo fa in un modo piccolo - Le stringhe Python '__repr__' mirano a essere espressioni Python valide - se non fosse per ellissi esistenti nella lingua come fa, la rappresentazione non sarebbe un'espressione valida. –

+2

@Lattyware Bene, è vero che il design originale è così inteso. Intende anche che 'eval (repr (a))' miri ad essere uguale a 'a'. Sfortunatamente è falso di tanto in tanto nella pratica, anche per i tipi built-in. Prova questo: 'a = []; a.append (a); eval (repr (a)) '. 'repr (a)' è '[[...]]', espressione non valida in Python 2. (In Python 3 è valido, ma il risultato di valutazione è qualcosa di diverso, ancora contrario all'intenzione originale). – chys

3

__getitem__ esempi minimi

serve come un valore magico classe singleton che viene inviata al __getitem__ quando si utilizza la ... sintassi "magic-looking".

La classe può quindi fare tutto ciò che vuole con esso.

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

Il Python incorporato list classe sceglie di dare la semantica di un intervallo, e qualsiasi utilizzo sano di esso dovrebbe troppo, naturalmente.

Personalmente, starei semplicemente lontano da esso nelle mie API e creare invece un metodo separato, più esplicito.

24

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

Esempio 1:

lunghezza arbitraria tuple omogenei possono essere espresse utilizzando uno tipo e ellissi, per esempio Tuple[int, ...]

Esempio 2:

È possibile dichiarare il tipo di ritorno di un callable senza specificare la firma della chiamata sostituendo un puntino di sospensione (tre punti) per l'elenco degli argomenti:

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

come detto da @ noɥʇʎԀʎzɐɹƆ e @phoenix - Si può infatti utilizzare in file stub. per esempio.

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

Maggiori informazioni ed esempi di come utilizzare questa puntini di sospensione possono essere scoperti qui https://www.python.org/dev/peps/pep-0484/#stub-files