with tutorial the español applications python recursion list recursive-datastructures

python - tutorial - the django project



Lista confusa[...] en Python: ¿qué es? (9)

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?). La fuente de este bucle infinito y por qué no se expande mientras se expande cuando se accede es algo en lo que estoy completamente perdido, sin embargo

Mira el siguiente código:

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

¿Cómo se supone que Python debe imprimir un? Es una lista que contiene un cero y una referencia a sí mismo. 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 de malo con la estructura recursiva de datos en sí misma. 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 trata el problema del infinito imprimiendo solo los puntos suspensivos, como se señaló en las respuestas anteriores.

Así que estaba escribiendo un árbol binario simple 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?). La fuente de este bucle infinito y por qué no se expande mientras se expande cuando se accede es algo en lo que estoy completamente perdido, sin embargo

>>> 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 que usa 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 que usa [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 [...]?


Creo que su "árbol" se contiene a sí mismo, por lo tanto, contiene ciclos.

Prueba este código:

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

Las primeras impresiones de salida:

[1,2,3,4]

mientras que el segundo:

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

El motivo es usar

def Keys(x,y=[]): Esto es malo y malvado La lista es un objeto mutable, y cuando se usa como un parámetro predeterminado, se conserva entre llamadas a funciones. Entonces cada operación y + = "cualquier cosa" se agrega a la misma lista (en todas las llamadas a funciones, y dado que 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.


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 una buena parte del conocimiento de back-shelf si encuentra una Elipsis en algún código real, en lugar de la salida.

El objeto Ellipsis en Python se usa para notación de división extendida. No se usa en las bibliotecas centrales actuales de Python, pero está disponible para que los desarrolladores lo definan en sus propias bibliotecas. Por ejemplo, NumPy (o SciPy) usan esto como parte de su objeto de matriz. Tendrá que mirar 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 Elipsis

Este objeto se usa mediante notación de división extendida (consulte el Manual de referencia de Python). No admite operaciones especiales. Hay exactamente un objeto de puntos suspensivos, llamado Ellipsis (un nombre incorporado).

Está escrito como Ellipsis.


No entiendo tu código anterior, pero el [...] creo que es el intérprete de Python que omite estructuras de datos infinitas. Por ejemplo:

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

Parece que la estructura de tu árbol se está haciendo un bucle.

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


Ok, entonces en puntos:

  1. Está creando una estructura de datos infinita:

    def Keys(x,y=[]) usará la misma ''y'' en cada llamada. Esto simplemente no es correcto.

  2. La declaración de print , sin embargo, es lo suficientemente inteligente como para no imprimir datos infinitos, sino para marcar la autorreferencia con un [...] (conocido como Ellipsis )

  3. Python le permitirá abordar dicha estructura correctamente, para que pueda 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 de manera más sólida con y = list(y)

Intenta usar el siguiente código:

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

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

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

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

def mKeys(x,y=None): if y is None: y = [] if len(x): z = [x[2], mKeys(x[0], y), mKeys(x[1],y)] return z return []


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

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

El valor del lado derecho de esta declaración es una lista que contiene x [2], más los ELEMENTOS DE las teclas (x [0], y) y los ELEMENTOS DE las teclas (x [1], y)

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

El valor del lado derecho en esta declaración es una lista que contiene x [2], más las teclas LISTAR (x [2], y) y las teclas LISTAR (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. Dado que en python, el objeto de valor predeterminado se crea una vez cuando se define la función, la primera versión no funcionará como se muestra en el ejemplo. Contendrá una copia múltiple de algunas claves. Es difícil de explicar en pocas palabras, pero puede hacerse una idea imprimiendo los valores de x, y en cada llamada de Keys.

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

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

    Puede ver esto llamando Llaves (a) dos veces o llamándola en dos listas diferentes.

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

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

    Definir una función recursiva básicamente contiene dos partes, resolver subproblemas y combinar los resultados. En su código, la parte de resultados de combinación se repite dos veces: una al acumularlas en y, una al sumar la lista.


También puede aparecer si tiene una estructura circular con una lista apuntando 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 ciclo infinito) utiliza los puntos suspensivos para mostrar que hay recursión en la estructura.

No estoy seguro de si la pregunta fue qué sucede o cómo solucionarlo, pero intentaré corregir las funciones anteriores.

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

O simplemente recopile toda la información sin agregar ninguna y , con algo como

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

o simplemente agregue 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, estos dos fragmentos necesitan tratamiento para listas vacías, etc.)

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


Si hubieras usado una PrettyPrinter, la salida habría sido autoexplicativa

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

En otras palabras, es algo así como


El problema se debe a que uno de los elementos de la lista hace referencia a la lista en sí. Entonces, si se intenta 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í] ( http://pythontutor.com/visualize.html#code=x+%3D+range(3%29%0Ax.append(x%29%0Ax%5B3%5D%5B3%5D % 5B3% 5D% 5B3% 5D% 5B3% 5D% 5B0% 5D +% 3D + 5% 0Aprint + x & mode = display & origin = opt-frontend.js & cumulative = false & heapPrimitives = false & textReferences = false & py = 2 & rawInputLstJSON =% 5B% 5D & curInstr = 4 )