Confuso Lista en Python: ¿Qué es?

Así que estaba escribiendo un simple árbol binario en Python y me encontré con […]

No creo que esto esté relacionado con el objeto Ellipsis, más parece que tiene algo que ver con un bucle infinito (¿debido a la copia superficial de Python?). Sin embargo, la fuente de este bucle infinito y por qué no se expande mientras se expande cuando se accede es algo que estoy completamente perdido.

 >>> a [[[[[], [], 8, 3], [[], [], 3, 2], 6, 3], [], 1, 4], [[], [], -4, 2], 0, 0] >>> Keys(a)#With a+b [0, 1, 6, 8, 3, -4] >>> Keys(a)#With [a,b] [8, [...], [...], 3, [...], [...], 6, [...], [...], 1, [...], [...], -4, [...], [...], 0, [...], [...]] >>> Keys(a)[1]#?? [8, [...], [...], 3, [...], [...], 6, [...], [...], 1, [...], [...], -4, [...], [...], 0, [...], [...], 8, [...], [...], 3, [...], [...], 6, [...], [...], 1, [...], [...], -4, [...], [...], 0, [...], [...]] 

Versión utilizando a + b

 def Keys(x,y=[]): if len(x):y+=[x[2]]+Keys(x[0],y)+Keys(x[1],y)#Though it seems I was using y=y[:]+, this actually outputs an ugly mess return y 

versión utilizando [a, b]

 def Keys(x,y=[]): if len(x):y+=[x[2],Keys(x[0],y),Keys(x[1],y)] return y 

Entonces, ¿qué es exactamente […]?

    También puede aparecer si tiene una estructura circular con una lista que apunta a sí misma. Me gusta esto:

     >>> a = [1,2] >>> a.append(a) >>> a [1, 2, [...]] >>> 

    Como Python no puede imprimir la estructura (sería un bucle infinito) utiliza los puntos suspensivos para mostrar que hay una recursión en la estructura.


    No estoy seguro de si la pregunta era qué sucedía o cómo solucionarlo, pero intentaré corregir las funciones anteriores.

    En ambos, primero hace dos llamadas recursivas, que agregan datos a la lista y , y luego, nuevamente, agrega los datos devueltos a y . Esto significa que los mismos datos estarán presentes varias veces en el resultado.

    O bien simplemente recostack todos los datos sin agregar nada a y , con algo como

     return [x[2]]+keys(x[0])+keys(x[1]) 

    o simplemente hacer el adjunto en las llamadas, con algo como

     y += [x[2]] keys(x[0], y) #Add left children to y... keys(x[1], y) #Add right children to y... return y 

    (Por supuesto, ambos fragmentos de código deben manejarse para listas vacías, etc.)

    @Abgan también notó que realmente no quiere que y=[] en el inicializador.

    Creo que tu ‘árbol’ se contiene a sí mismo, por lo tanto contiene ciclos.

    Prueba este código:

        a = [1,2,3,4]
        imprimir un
        a.append (a)
        imprimir un
    

    Las primeras salidas de impresión:

       [1,2,3,4]
    

    mientras que el segundo

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

    La razón es usar

      Teclas def (x, y = []):
     

    Esto es malo y malo. La lista es un objeto mutable, y cuando se usa como parámetro predeterminado, se conserva entre las llamadas a funciones. Por lo tanto, cada operación y + = “cualquier cosa” se agrega a la misma lista (en todas las llamadas a funciones, y como la función es recursiva …)


    Consulte Effbot o Devshed para obtener más detalles sobre los objetos mutables pasados ​​como valores predeterminados para las funciones.

    No entiendo su código anterior, pero creo que el […] intérprete de Python se salta infinitas estructuras de datos. Por ejemplo:

     >>> a = [0, 1] >>> a[0] = a >>> a [[...], 1] 

    Parece que la estructura de tu árbol se está volviendo en bucle.

    Las respuestas sobre los objetos de corte están al lado del punto.

    No creo que esto esté relacionado con el objeto Ellipsis, más parece que tiene algo que ver con un bucle infinito (¿debido a la copia superficial de Python?). Sin embargo, la fuente de este bucle infinito y por qué no se expande mientras se expande cuando se accede es algo que estoy completamente perdido.

    Mira el siguiente código:

     >>> a = [0] >>> a.append(a) >>> print a [0, [...]] 

    ¿Cómo se supone que Python debe imprimir una? Es una lista que contiene un cero y una referencia a sí misma. Por lo tanto, es una lista que contiene un cero y una referencia a una lista.

     [0, [...]] 

    que a su vez contiene un cero y una referencia a una lista

     [0, [0, [...]]] 

    que a su vez contiene un cero y una referencia a una lista, y así sucesivamente, recursivamente:

     [0, [0, [0, [...]]]] [0, [0, [0, [0, [...]]]]] [0, [0, [0, [0, [0, [...]]]]]] ... 

    No hay nada malo con la estructura de datos recursiva en sí. El único problema es que no se puede mostrar , ya que esto implicaría una recursión infinita. Por lo tanto, Python se detiene en el primer paso de recursión y se ocupa del problema infinito de imprimir solo los puntos suspensivos, como se señaló en las respuestas anteriores.

    Si hubiera usado una PrettyPrinter, la salida se habría explicado por sí misma.

     >>> l = [1,2,3,4] >>> l[0]=l >>> l [[...], 2, 3, 4] >>> pp = pprint.PrettyPrinter(indent = 4) >>> pp.pprint(l) [, 2, 3, 4] >>> id(l) 70327632 

    En otras palabras, es algo así como

    introduzca la descripción de la imagen aquí

    EDITAR: Como se mencionó anteriormente, este no es el objeto Ellipsis, sino el resultado de una lista en bucle. Salté el arma aquí. Conocer el objeto Ellipsis es un buen conocimiento de la plataforma de almacenamiento en caso de que encuentre un Ellipsis en algún código real, en lugar de en el resultado.


    El objeto Ellipsis en Python se usa para la notación de sector extendido. No se usa en las bibliotecas centrales de Python actuales, pero está disponible para que los desarrolladores lo definan en sus propias bibliotecas. Por ejemplo, NumPy (o SciPy) usa esto como parte de su objeto de matriz. Deberá consultar la documentación de tree () para saber exactamente cómo se comporta Ellipsis en este objeto.

    De la documentación de Python :

    3.11.8 El objeto de la elipsis

    Este objeto es usado por la notación de división extendida (consulte el Manual de referencia de Python). No soporta operaciones especiales. Hay exactamente un objeto de puntos suspensivos, denominado Elipsis (un nombre incorporado).

    Está escrito como elipsis.

    Ok, así que en puntos:

    1. Estás creando una estructura de datos infinita:

        Teclas def (x, y = []) 

      Utilizará la misma ‘y’ en cada llamada. Esto simplemente no es correcto.

    2. La statement de print , sin embargo, es lo suficientemente inteligente como para no imprimir datos infinitos, sino para marcar la auto-referencia con una […] (conocida como elipsis )

    3. El Python le permitirá abordar dicha estructura correctamente, por lo que puede escribir
        a.keys () [1] [1] [1] 

      y así. ¿Por qué no deberías?

    4. La instrucción y = y[:] simplemente copia la lista y. Se puede hacer más profundamente con y = list(y)

    Intenta usar el siguiente código:

     Teclas def (x, y = Ninguna):
         si y es ninguno:
             y = []
         si len (x):
             y + = [x [2], Teclas (x [0], y), Teclas (x [1], y)]
         volver y
    

    Pero aun así supongo que te puede morder. Todavía estás usando la misma variable y (me refiero al mismo objeto) en tres lugares en una expresión:

      y + = [x [2], Teclas (x [0], y), Teclas (x [1], y)] 

    ¿Es eso lo que realmente quieres lograr? O tal vez deberías intentar:

     def mKeys (x, y = None):
         si y es ninguno:
             y = []
         si len (x):
            z = [x [2], mKeys (x [0], y), mKeys (x [1], y)]
            retorno z
        regreso []
    

    Para la diferencia entre las dos versiones de las teclas de función, tenga en cuenta la siguiente diferencia:

     y+=[x[2]]+Keys(x[0],y)+Keys(x[1],y) 

    El valor del lado derecho en esta statement es una lista que contiene x [2], más los ELEMENTOS DE las claves (x [0], y) y los ELEMENTOS DE las claves (x [1], y)

     y+=[x[2],Keys(x[0],y),Keys(x[1],y)] 

    El valor del lado derecho en esta statement es una lista que contiene x [2], más las teclas LIST (x [2], y) y las teclas LIST (x [1], y).

    Entonces, la versión que usa [a, b] causará que y se contenga a sí misma como sus elementos.

    Algunas otras notas:

    1. Como en Python, el objeto de valor predeterminado se crea una vez que se define la función, la primera versión no funcionará como se muestra en el ejemplo. Contendrá múltiples copias de algunas claves. En resumen, es difícil de explicar, pero puede hacerse una idea imprimiendo los valores de x, y en cada llamada de teclas.

      Esto se confirma ejecutando la función en mi máquina con Python 2.5.2.

    2. Además, debido a que el valor predeterminado se define solo una vez en el momento de la definición de la función, incluso la función funciona correctamente por primera vez, no funcionará cuando se llame con una a diferente, ya que las claves del primer árbol binario permanecerán en y.

      Puede ver esto llamando a las teclas (a) dos veces, o llamándolo en dos listas diferentes.

    3. El segundo parámetro no es necesario para este problema. La función puede ser así:

      Teclas def (a): si a = []: return [] else: return [a [2]] + Teclas (a [0]) + Teclas (a [1])

      La definición de una función recursiva contiene básicamente dos partes, resuelve subproblemas y combina los resultados. En su código, la parte de la combinación de resultados se repite dos veces: una acumulando en y, una agregando la lista.

    El problema es porque uno de los elementos de la lista hace referencia a la propia lista. Entonces, si se hace un bash de imprimir todos los elementos, nunca terminará.

    Ilustración:

     x = range(3) x.append(x) x[3][3][3][3][3][0] = 5 print x 

    Salida:

     [5, 1, 2, [...]] 

    x[3] es una referencia a x sí. Lo mismo ocurre con x[3][3] .

    Esto se puede visualizar mejor aquí.