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.