Python OOP y listas

Soy nuevo en Python y son cosas de POO y no puedo hacer que funcione. Aquí está mi código:

class Tree: root = None; data = []; def __init__(self, equation): self.root = equation; def appendLeft(self, data): self.data.insert(0, data); def appendRight(self, data): self.data.append(data); def calculateLeft(self): result = []; for item in (self.getLeft()): if (type(item) == type(self)): data = item.calculateLeft(); else: data = item; result.append(item); return result; def getLeft(self): return self.data; def getRight(self): data = self.data; data.reverse(); return data; tree2 = Tree("*"); tree2.appendRight(44); tree2.appendLeft(20); tree = Tree("+"); tree.appendRight(4); tree.appendLeft(10); tree.appendLeft(tree2); print(tree.calculateLeft()); 

Parece que tree2 y tree están compartiendo la lista de “datos”?

En este momento me gustaría que emita algo como [[20,44], 10, 4], pero cuando

 tree.appendLeft(tree2) 

Obtengo RuntimeError: maximum recursion depth exceeded , y cuando ni siquiera puedo appendLeft(tree2) , genera [10, 20, 44, 4] (!!!). ¿Que me estoy perdiendo aqui? Estoy usando Portable Python 3.0.1.

Gracias

El problema es que ha declarado los data como una variable de clase, por lo que todas las instancias de la clase comparten la misma lista. En su lugar, coloca self.data = [] en tu __init__ .

Además, deshacerse de todos esos puntos y comas. Son innecesarios y desordenan tu código.

Mueva la raíz y los datos a la definición de __init__ . En su estado actual, los tiene definidos como atributos de clase. Eso los hace compartir entre todas las instancias de la clase Tree. Cuando tree2 instancia de dos árboles ( tree y tree2 ), ambos comparten la misma lista a la que accedió con self.data . Para hacer que cada instancia tenga su propio atributo de instancia, debe mover la statement a la función __init__ .

 def __init__(self, equation): self.root = equation self.data = [] 

Además, usar

  if isinstance(item,Tree): # This is True if item is a subclass of Tree 

en lugar de

  if (type(item) == type(self)): # This is False if item is a subclass of Tree 

y cambio

 data = self.data 

a

 data = self.data[:] 

en getRight . Cuando dice data = self.data , los data nombre de variable apuntan a la misma lista a la que apunta self.data . Cuando posteriormente invierte data , también invierte self.data . Para invertir solo los data , debe copiar la lista. self.data[:] utiliza la notación de corte para devolver una copia de la lista. Tenga en cuenta que los elementos de self.data pueden ser Tree s, y self.data y self.data[:] pueden contener elementos idénticos. No creo que su código requiera la copia de estos elementos, pero tendrá que copiarse de forma recursiva self.data si ese es el caso.

 def getRight(self): data = self.data[:] data.reverse() return data 

Cuando definas atributos de la siguiente manera:

 class Tree: root = None data = [] 

..que el objeto de lista vacía se crea como Python define la clase, no cuando creas una nueva instancia. Es un atributo de clase, no un atributo de instancia. Es decir, Tree.root es el mismo objeto en todos los casos:

 class Tree: root = None data = [] t1 = Tree() t2 = Tree() print id(t1.data) == id(t2.data) # is True, they are the same object 

Para obtener el comportamiento que espera, mueva la creación de la lista vacía a la función __init__ , a la que solo se llama cuando crea una nueva instancia, y solo altera esa instancia (como se asigna a self ):

 class Tree: def __init__(self): self.root = None self.data = [] t1 = Tree() t2 = Tree() print id(t1.data) == id(t2.data) # False, they are different objects 

Esta pregunta explica por qué tal comportamiento puede ser útil.