Cosa significano i puntini di sospensione […] in un elenco?


196

Stavo giocando in pitone. Ho usato il seguente codice in IDLE:

p  = [1, 2]
p[1:1] = [p]
print p

L'output è stato:

[1, [...], 2]

Che cos'è questo […]? È interessante notare che ora potrei usare questo come un elenco di elenco di elenchi fino all'infinito, cioè

p[1][1][1]....

Potrei scrivere quanto sopra quanto volevo e funzionerebbe ancora.

MODIFICARE:

  • Come viene rappresentato in memoria?
  • A che serve? Esempi di alcuni casi in cui è utile sarebbero utili.
  • Qualsiasi collegamento alla documentazione ufficiale sarebbe davvero utile.

Sto ancora cercando le risposte al primo e al terzo elemento dell'elenco di EDIT.
Aseem Bansal,

7
Un esempio più semplice sarebbe p = [1]; p[0] = p.
Arshajii,

6
Penso che questo sia un duplicato di Cosa significa […] (un'ellissi) in un elenco in Python? , sebbene la domanda (e le risposte) siano migliori in questa domanda.
Martin Thoma,

1
Dreampie è intelligente `>>> p [1: 1] = [p] >>> p 3: [1, <Ricorsione in elenco con ID = 3074777548>, 2] >>>` fornisce i dettagli esatti
Rahul Gautam

@RahulGautam Non l'ho capito p 3: [1, <Recursion on list with id=3074777548>, 2]. Che cosa hai corso?
Aseem Bansal,

Risposte:


112

Significa che hai creato un elenco infinito nidificato al suo interno, che non può essere stampato. pcontiene pquale contiene p... e così via. La [...]notazione è un modo per farti sapere questo e per informare che non può essere rappresentato! Dai un'occhiata alla risposta di @ 6502 per vedere una bella foto che mostra cosa sta succedendo.

Ora, per quanto riguarda i tre nuovi elementi dopo la modifica:

  • Questa risposta sembra coprirla
  • Il link di Ignacio descrive alcuni possibili usi
  • Questo è più un argomento di progettazione della struttura dei dati che di linguaggi di programmazione, quindi è improbabile che qualsiasi riferimento si trovi nella documentazione ufficiale di Python

Quindi sta prendendo l'infinito ricordo? So che non può essere possibile. Come viene rappresentato e a cosa serve?
Aseem Bansal,

21
@Zel: gli elementi dell'elenco sono riferimenti. Il secondo elemento è un riferimento all'elenco stesso.
Ignacio Vazquez-Abrams,

2
Python lo ha identificato come un ciclo infinito di riferimenti, quindi ha deciso di interromperlo, non è davvero infinito. E no, oltre a un esperimento mentale non è molto utile :)
Óscar López,

2
Ci sono ... alcuni usi per strutture infinitamente ricorsive. Ma non molti.
Ignacio Vazquez-Abrams,

@ IgnacioVazquez-Abrams Alcuni esempi potrebbero essere utili.
Aseem Bansal,

316

Questo è ciò che il tuo codice ha creato

inserisci qui la descrizione dell'immagine

È un elenco in cui il primo e l'ultimo elemento indicano due numeri (1 e 2) e in cui l'elemento centrale punta all'elenco stesso.

In Common Lisp quando la stampa di strutture circolari è abilitata, tale oggetto verrebbe stampato come

#1=#(1 #1# 2)

nel senso che esiste un oggetto (etichettato 1 con #1=) che è un vettore con tre elementi, il secondo è l'oggetto stesso (con riferimento all'indietro #1#).

In Python invece ottieni solo le informazioni con cui la struttura è circolare [...].

In questo caso specifico la descrizione non è ambigua (punta all'indietro verso un elenco ma esiste solo un elenco, quindi deve essere quello). In altri casi può essere comunque ambiguo ... per esempio in

[1, [2, [...], 3]]

il riferimento all'indietro potrebbe indicare l'esterno o l'elenco interno. Queste due diverse strutture stampate nello stesso modo possono essere create con

x = [1, [2, 3]]
x[1][1:1] = [x[1]]

y = [1, [2, 3]]
y[1][1:1] = [y]

print(x)
print(y)

e sarebbero in memoria come

inserisci qui la descrizione dell'immagine


Puoi trovare il contenuto di [1, [2, [...], 3]]questo tipo: x[1] = [2, [...], 3]e y[1] = [2, 1, [...]], 3]. Ciò significa che x è costituito da un 1 e quindi ripetendo 2 secondi, mentre y consiste alternando 1 secondi e 2 secondi.
Pascalhein,

2
@csharpler: ovviamente puoi distinguere i due analizzando il contenuto, tuttavia sono stampati con la stessa rappresentazione. Nel formato Common Lisp invece sarebbero #(1 #1=#(2 #1# 3))per xe #1=#(1 #(2 #1# 3))per y.
6502

5
@BurhanKhalid: inkscape per il primo e gimp per il secondo (perché ho buttato via lo svg)
6502

1
@csharpler: non è possibile creare un "elenco infinito" in Python perché gli elenchi sono effettivamente array ridimensionabili, non elenchi collegati. È possibile invece creare un "elenco infinito" in Common Lisp #1=(1 . #1#).
6502

1
+ se vuoi disegnare un diagramma acsii come questo prova: Asiiflow
Grijesh Chauhan

23

Alla domanda "A cosa serve", ecco un esempio concreto.

La riduzione del grafico è una strategia di valutazione utilizzata a volte per interpretare un linguaggio informatico. Questa è una strategia comune per la valutazione pigra, in particolare dei linguaggi funzionali.

Il punto di partenza è costruire un grafico che rappresenti la sequenza di "passi" che il programma prenderà. A seconda delle strutture di controllo utilizzate in quel programma, questo potrebbe portare a un grafico ciclico (perché il programma contiene una sorta di ciclo "per sempre") o utilizzare la ricorsione la cui "profondità" sarà nota al momento della valutazione , ma non al grafico- tempo di creazione ) ...

Per rappresentare tale grafico, hai bisogno di infinite "strutture di dati" (a volte chiamate strutture di dati ricorsive ), come quella che hai notato. Di solito, un po 'più complesso però.

Se sei interessato a quell'argomento, ecco (tra molti altri) una lezione sull'argomento:
http://undergraduate.csse.uwa.edu.au/units/CITS3211/lectureNotes/14.pdf


7

Lo facciamo continuamente nella programmazione orientata agli oggetti. Se due oggetti si riferiscono l'un l'altro, direttamente o indirettamente, sono entrambe strutture infinitamente ricorsive (o entrambe parti della stessa struttura infinitamente ricorsiva, a seconda di come la guardi). Ecco perché non vedi così tanto in qualcosa di primitivo come un elenco - perché di solito stiamo meglio descrivendo il concetto come "oggetti" interconnessi piuttosto che un "elenco infinito".

Puoi anche ottenere ...con un dizionario infinitamente ricorsivo. Supponiamo che tu voglia un dizionario degli angoli di un triangolo, dove ogni valore è un dizionario degli altri angoli collegati a quell'angolo. Puoi configurarlo in questo modo:

a = {}
b = {}
c = {}
triangle = {"a": a, "b": b, "c": c}
a["b"] = b
a["c"] = c
b["a"] = a
b["c"] = c
c["a"] = a
c["b"] = b

Ora, se si stampa triangle(o ao bo cper quella materia), vedrete che è pieno di {...}perché ogni due angoli si riferiscono alla parte posteriore gli uni agli altri.


Esempio di dizionario più semplice:a = {}; a['a'] = a; print a['a']['a']['a']
user650654

Per me, invece di "..." mostra "<Ricorsione su dict con id = ___>"
Solomon Ucko,

@SolomonUcko Probabilmente stai usando IPython che utilizza automaticamente pprint per stampare cose. Se digiti %pprintper disattivare la stampa carina, verrà visualizzato ....
nmclean,

4

Come ho capito, questo è un esempio di punto fisso

p  = [1, 2]
p[1:1] = [p]
f = lambda x:x[1]
f(p)==p
f(f(p))==p

Non sono stato in grado di capirlo. Ho provato a eseguire questi comandi ma ci sono errori.
Aseem Bansal,

@Zel: Bene, devi aggiungere il codice OP prima di esso in modo che p sia dichiarato.
Inkane,

1
@Zel: Beh, non sono sicuro di quanto sia utile me stesso, ma Firegun dice che p (e quindi p [1], rappresentato come [...]) è un punto fisso della funzione f. IMHO, questa è una possibile risposta alla domanda "Cos'è [...]?" in questo caso.
Inkane,

1
Ho avuto lo stesso problema di errore perché avevo provato questo esempio dopo aver provato l' p = [1]; p[0] = pesempio più semplice che deve f = lambda x:x[0]funzionare. È un esempio di un punto fisso, ma non sono stato ancora in grado di vedere come conoscere questo sia utile. Il vero valore del punto di correzione sta arrivando da un altro punto in modo ricorsivo o iterativo. Un esempio che mostra come utilizzare la struttura dell'elenco della domanda originale per creare il combinatore Y sarebbe utile se è possibile.
dansalmo,

1
q = lambda: qproduce un lambda a
chiamata

-2

Il nome di quell'oggetto speciale è l'ellissi. Immagino che sia implementato come un oggetto singleton nell'interprete / VM di Python - qualcosa come None --- una specie di sentinella. Come hai visto, Python rappresenta un modo per rappresentare il riferimento di un elenco al suo interno.


Stranamente non sembra esserci modo di istanziare direttamente un oggetto Ellissi. Ad esempio, il nome non è esposto tramite l'interfaccia Builtins. Quindi puoi vedere i riferimenti al termine in alcuni errori (sollevate eccezioni) ad esempio se tenti di estrarre un elemento usando i puntini di sospensione come indice. Ma puoi semplicemente dire: el = Ellipsis () né niente del genere (che ho trovato).
Jim Dennis,

9
Questo in realtà non ha nulla a che fare con l'oggetto Ellissi. È solo la stringa letterale "[...]", che viene stampata quando viene rilevato un ciclo durante la stampa di un elenco. Vedi codice: hg.python.org/cpython/file/84d6c1c0665e/Objects/…
Jeremy Sharpe
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.