¿Qué significan los puntos suspensivos [...] en una lista?

196

Estaba jugando en python. Usé el siguiente código en IDLE:

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

El resultado fue:

[1, [...], 2]

¿Qué es esto […]? Curiosamente, ahora podría usar esto como una lista de lista de lista hasta el infinito, es decir

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

Podría escribir lo anterior todo el tiempo que quisiera y aún funcionaría.

EDITAR:

  • ¿Cómo se representa en la memoria?
  • ¿De qué sirve? Ejemplos de algunos casos donde es útil sería útil.
  • Cualquier enlace a la documentación oficial sería realmente útil.
Aseem Bansal
fuente
Todavía estoy buscando respuestas para el 1er y 3er elemento de la lista EDIT.
Aseem Bansal
77
Un ejemplo más simple sería p = [1]; p[0] = p.
arshajii
66
Creo que esto es un duplicado de ¿Qué significa [...] (una elipsis) en una lista en Python? , aunque la pregunta (y las respuestas) son mejores en esta pregunta.
Martin Thoma
1
Dreampie es inteligente `>>> p [1: 1] = [p] >>> p 3: [1, <Recursión en la lista con id = 3074777548>, 2] >>>` proporciona los detalles exactos
Rahul Gautam
@RahulGautam No entendí esto p 3: [1, <Recursion on list with id=3074777548>, 2]. ¿Qué corriste?
Aseem Bansal

Respuestas:

112

Significa que creó una lista infinita anidada dentro de sí misma, que no se puede imprimir. pcontiene pque contiene p... y así sucesivamente. ¡La [...]notación es una manera de hacerle saber esto y de informarle que no se puede representar! Eche un vistazo a la respuesta de @ 6502 para ver una bonita imagen que muestra lo que está sucediendo.

Ahora, con respecto a los tres nuevos elementos después de su edición:

  • Esta respuesta parece cubrirlo
  • Enlace de Ignacio describe algunos usos posibles
  • Este es más un tema de diseño de estructura de datos que lenguajes de programación, por lo que es poco probable que se encuentre alguna referencia en la documentación oficial de Python.
Óscar López
fuente
Entonces, ¿está tomando memoria infinita? Sé que eso no puede ser posible. ¿Cómo se representa y para qué sirve?
Aseem Bansal
21
@Zel: los elementos de la lista son referencias. El segundo elemento es una referencia a la lista misma.
Ignacio Vazquez-Abrams
2
Python lo identificó como un bucle infinito de referencias, por lo que decidió acortarlo, no es realmente infinito. Y no, no es realmente útil además de un experimento mental :)
Óscar López
2
Hay ... algunos usos para estructuras infinitamente recursivas. Pero no muchos.
Ignacio Vazquez-Abrams
@ IgnacioVazquez-Abrams Algunos ejemplos serían útiles.
Aseem Bansal
316

Esto es lo que creó tu código

ingrese la descripción de la imagen aquí

Es una lista donde el primer y el último elemento apuntan a dos números (1 y 2) y el elemento central apunta a la lista misma.

En Common Lisp, cuando la impresión de estructuras circulares está habilitada, dicho objeto se imprimiría como

#1=#(1 #1# 2)

lo que significa que hay un objeto (etiquetado con 1 #1=) que es un vector con tres elementos, el segundo es el objeto mismo (referenciado con #1#).

En Python, solo obtienes la información con la que la estructura es circular [...].

En este caso específico, la descripción no es ambigua (apunta hacia atrás a una lista, pero solo hay una lista, por lo que debe ser esa). En otros casos puede ser sin embargo ambiguo ... por ejemplo en

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

la referencia hacia atrás podría apuntar a la lista externa o interna. Estas dos estructuras diferentes impresas de la misma manera se pueden crear con

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

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

print(x)
print(y)

y estarían en la memoria como

ingrese la descripción de la imagen aquí

6502
fuente
Puede encontrar el contenido de [1, [2, [...], 3]]esta manera: x[1] = [2, [...], 3]y y[1] = [2, 1, [...]], 3]. Esto significa que x consiste en un 1 y luego repite 2s, mientras que y consiste en alternar 1s y 2s.
pascalhein
2
@csharpler: por supuesto, puede distinguir los dos analizando el contenido, sin embargo, se imprimen con la misma representación. En formato Common Lisp, en cambio, serían #(1 #1=#(2 #1# 3))para xy #1=#(1 #(2 #1# 3))para y.
6502
55
@BurhanKhalid: Inkscape para el primero y Gimp para el segundo (porque tiré el svg)
6502
1
@csharpler: no puede crear una "lista infinita" en Python porque las listas son matrices redimensionables, no listas enlazadas. En cambio, se podría crear una "lista infinita" en Common Lisp #1=(1 . #1#).
6502
1
+ si quieres dibujar un diagrama acsii como este intenta: Asiiflow
Grijesh Chauhan
23

A la pregunta "¿De qué sirve?", Aquí hay un ejemplo concreto.

La reducción de gráficos es una estrategia de evaluación que se usa alguna vez para interpretar un lenguaje de computadora. Esta es una estrategia común para la evaluación diferida, especialmente de lenguajes funcionales.

El punto de partida es construir un gráfico que represente la secuencia de "pasos" que tomará el programa. Dependiendo de las estructuras de control utilizadas en ese programa, esto podría conducir a un gráfico cíclico (porque el programa contiene algún tipo de bucle "para siempre", o utilizar la recursión cuya "profundidad" se conocerá en el momento de la evaluación , pero no en el gráfico). tiempo de creación ) ...

Para representar dicho gráfico, necesita infinitas "estructuras de datos" (a veces llamadas estructuras de datos recursivas ), como la que notó. Por lo general, un poco más complejo sin embargo.

Si está interesado en ese tema, aquí hay (entre muchos otros) una conferencia sobre ese tema:
http://undergraduate.csse.uwa.edu.au/units/CITS3211/lectureNotes/14.pdf

Sylvain Leroux
fuente
7

Hacemos esto todo el tiempo en la programación orientada a objetos. Si dos objetos se refieren entre sí, directa o indirectamente, ambos son estructuras infinitamente recursivas (o ambas partes de la misma estructura infinitamente recursiva, dependiendo de cómo se mire). Es por eso que no ves tanto en algo tan primitivo como una lista, porque generalmente es mejor describir el concepto como "objetos" interconectados que una "lista infinita".

También puede obtener ...con un diccionario infinitamente recursivo. Digamos que desea un diccionario de las esquinas de un triángulo, donde cada valor es un diccionario de las otras esquinas conectadas a esa esquina. Podrías configurarlo así:

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

Ahora, si imprime triangle(o ao bo cpara el caso), verá que está lleno {...}porque cualquiera de las dos esquinas se refieren entre sí.

nmclean
fuente
Ejemplo de diccionario más simple:a = {}; a['a'] = a; print a['a']['a']['a']
user650654
Para mí, en lugar de "..." muestra "<Recursion on dict with id = ___>"
Solomon Ucko
@SolomonUcko Probablemente estés usando IPython que usa automáticamente pprint para imprimir cosas. Si escribe %pprintpara desactivar la impresión bonita, se mostrará ....
nmclean
4

Como entendí, este es un ejemplo de punto fijo

p  = [1, 2]
p[1:1] = [p]
f = lambda x:x[1]
f(p)==p
f(f(p))==p
Hanfei Sun
fuente
No he podido entender esto. Intenté ejecutar estos comandos pero hay errores.
Aseem Bansal
@Zel: Bueno, tienes que agregar el código de OP antes para que se declare p.
Inkane
1
@Zel: Bueno, no estoy seguro de lo útil que es para mí, pero Firegun dice que p (y por lo tanto p [1], representada como [...]) es un punto fijo de la función f. En mi humilde opinión, esta es una posible respuesta a la pregunta "¿Qué es [...]?" en este caso.
Inkane
1
Tuve el mismo problema de error porque probé este ejemplo después de probar el p = [1]; p[0] = pejemplo más simple que debe f = lambda x:x[0]funcionar. Es un ejemplo de un punto fijo, pero aún no he podido ver cómo saber esto es útil. El valor real del punto fijo llega a él desde algún otro punto de manera recursiva o iterativa. Un ejemplo que muestre cómo usar la estructura de lista de la pregunta original para crear el combinador Y sería útil si fuera posible.
dansalmo
1
q = lambda: qhace una lambda infinitamente invocable
whackamadoodle3000
-2

El nombre de ese objeto especial es Elipsis. Supongo que se implementa como un objeto singleton en el Python intepreter / VM, algo así como None, una especie de centinela. Como has visto, es una forma en que Python representa la referencia de una lista dentro de sí mismo.

Jim Dennis
fuente
Curiosamente, parece que no hay forma de instanciar directamente un objeto de puntos suspensivos. El nombre no se expone a través de la interfaz de Builtins, por ejemplo. Por lo tanto, puede ver referencias al término en ciertos errores (excepciones planteadas), por ejemplo, si intenta extraer un elemento utilizando puntos suspensivos como índice. Pero solo puedes decir: el = Ellipsis () ni nada de eso (que he encontrado).
Jim Dennis
9
En realidad, esto no tiene nada que ver con el objeto de puntos suspensivos. Es solo la cadena literal "[...]", que se imprime cuando se detecta un ciclo durante la impresión de una lista. Ver código: hg.python.org/cpython/file/84d6c1c0665e/Objects/…
Jeremy Sharpe