2008-12-29 11 views
15

Así que yo estaba escribiendo un árbol binario simple en Python y encontré [...]Lista confusa [...] en Python: ¿qué es?

no creo que esto se relaciona con el objeto de puntos suspensivos, más se parece tener algo que ver con una infinidad loop (debido a la copia superficial de Python?). La fuente de este bucle infinito y por qué no consigue expandió mientras se expande cuando se tiene acceso es algo 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 utilizando una versión 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 

usando [a , b]

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

¿Qué es exactamente [...]?

+0

favor ser más específico y al grano. – andHapp

+1

Querrá editar esto. Creo que el núcleo de su pregunta gira en torno al objeto Ellipsis, que es difícil de conocer si no lo ha visto antes (y es difícil encontrar los documentos incluso cuando lo sabe). –

+0

La forma actual de la pregunta no tiene ningún sentido. Si 'a' es (como se muestra) una lista de listas, entonces' a' no tiene el método 'keys()'. Por favor, corrija la pregunta para mostrar realmente lo que está haciendo en realidad. –

Respuesta

2

EDITAR: Como se mencionó anteriormente, este no es el objeto Ellipsis, sino el resultado de una lista de bucles. 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 utiliza para la notación de rebanada 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 Python documentation:

3.11.8 Los puntos suspensivos Objeto

Este objeto se utiliza por extendido notación rebanada (véase el Manual de Referencia Python ). No admite operaciones especiales . Hay exactamente un objeto ellipsis , llamado Ellipsis (un nombre incorporado ).

Está escrito como Ellipsis.

23

También puede aparecer si tiene una estructura circular con una lista apuntando a sí misma. De esta manera:

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

Desde pitón no puede imprimir la estructura (sería un bucle infinito) que utiliza los puntos suspensivos para mostrar que no hay recursividad en la estructura.


No estoy muy seguro de si la pregunta era lo que lo que sucede o cómo solucionarlo, pero voy a tratar de corregir las funciones anteriormente.

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

O simplemente recoger todos los datos sin necesidad de añadir a cualquier y, con algo como

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

o simplemente hacer la Anexión de 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, tanto estos fragmentos necesitan tratamiento para listas vacías, etc.)

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

5

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

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

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

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

6

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

probar este código:

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

Las primeras salidas de impresión:

 
    [1,2,3,4] 

mientras que el segundo:

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

La razón está utilizando

 
def Keys(x,y=[]): 
Esto está mal y el mal. La lista es un objeto mutable, y cuando se usa como un parámetro predeterminado, se conserva entre llamadas a funciones. Así que cada y + = funcionamiento "nada" se suma a la misma lista (en todas las llamadas a funciones, y dado que la función es recursiva ...)


Véase el Effbot o Devshed para más detalles sobre los objetos mutables pasados como valores por defecto para las funciones.

+0

Agregó y = y [:] a la parte superior de la versión [a, b] y obtuvo una salida de [[0], [[1], [[6], [[8], [], []] , [[3], [], []]], []], [[-4], [], []]] –

+0

Bueno, son las 4:27 a.m. en mi lugar, así que no me gusta mucho siguiendo los paréntesis. ¿Qué pasa con la salida? Y realmente debería usar "def Keys (x, y = None): si y es None: y = []" en su lugar. – Abgan

4

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

Mira el siguiente código:

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

Cómo es Python se supone que 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, de forma recursiva:

[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 trata el problema del infinito imprimiendo solo los puntos suspensivos, como se señaló en las respuestas anteriores.

+0

Sin embargo, cuando llama a [1] obtiene [0, [...]] nuevamente. En el caso de mi ejemplo, parece devolver una lista más grande en lugar de la misma lista. Quizás Python se está fusionando [...] + [...] en [...]? –

+0

Cuando llama a [1] obtiene [0, [...]] nuevamente: SÍ, porque a [1] es un sí mismo! –

1

Ok, por lo que en puntos:

  1. va a crear los datos infinitos estructura:

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

  2. La declaración print, sin embargo, es lo suficientemente inteligente como para no imprimir un conjunto de datos infinitas, pero para marcar autorreferencia con un [...] (conocidos como Puntos suspensivos )

  3. El pitón le permitirá para abordar dicha estructura correctamente, para que pueda escribir
    a.keys()[1][1][1]
    y así sucesivamente. ¿Por qué no deberías?
  4. La declaración y = y[:] simplemente copia la lista y. Se puede hacer más profundamente con y = list(y)

Trate de 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 aún así que supongo que se puede morder. Usted todavía está utilizando la misma variable y (me refiero a un mismo objeto) en tres sitios en una sola expresión:

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

es eso lo que realmente quieres lograr? O tal vez debería 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 [] 
1

Por 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 de lado derecho en esta declaración es una lista que contiene x [2], además de los elementos de Keys (x [0], y) y los elementos de teclas (x [1], y)

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

El valor 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] hará que y se contenga a sí mismo como sus elementos.

Algunas otras notas:

  1. Dado que en pitón, el objeto de valor predeterminado se crea una vez cuando se define la función, la primera versión no funcionará como el ejemplo muestra. 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 porque el valor predeterminado se define solo una vez en el tiempo de definición de función, incluso si la función funciona correctamente por primera vez, no funcionará al llamar con una 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 de esta manera:

    def Keys (a): si a = []: retorno [] cosa: retorno [a [2]] + Keys (a [0]) + Keys (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 resultados de combinación se repite dos veces: una al acumularlas en y, una al sumar la lista.

+0

Bastante elegante. Aunque tuve que cambiar un [2] por un [2]] –

3

Si ha utilizado un PrettyPrinter, la salida había sido explica por sí mismo

>>> 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 como

enter image description here

0

El problema se debe a que una de el elemento de 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)