5

我是 Python 新手,它是 OOP 的东西,无法让它工作。这是我的代码:

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());

看起来 tree2 和 tree 正在共享列表“数据”?

目前我希望它输出类似 [[20,44], 10, 4] 的东西,但是当我

tree.appendLeft(tree2) 

我得到了RuntimeError: maximum recursion depth exceeded,当我什至不会appendLeft(tree2)输出时[10, 20, 44, 4](!!!)。我在这里想念什么?我正在使用便携式 Python 3.0.1。

谢谢

4

3 回答 3

10

问题是您已将其声明data为类变量,因此该类的所有实例共享同一个列表。相反,放入self.data = []您的__init__.

此外,摆脱所有这些分号。它们是不必要的,并且会使您的代码混乱。

于 2010-05-20T23:14:08.617 回答
4

将根和数据移动到__init__. 就目前而言,您将它们定义为类属性。这使得它们在 Tree 类的所有实例之间共享。当您实例化两棵树 (treetree2) 时,它们都共享同一个使用 访问的列表self.data。要使每个实例都有自己的实例属性,您必须将声明移到__init__函数中。

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

另外,使用

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

代替

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

和改变

data = self.data

data = self.data[:]

getRight. 当您说时data = self.data,变量名称data指向指向的相同列表self.data。当您随后反转data时,您也反转self.data。要仅反转data,您必须复制列表。self.data[:]使用切片符号返回列表的副本。请注意, 的元素self.data可以是Trees,self.data并且self.data[:]可以包含相同的元素。我认为您的代码不需要复制这些元素,但self.data如果是这种情况,您将需要递归复制。

def getRight(self):
    data = self.data[:]
    data.reverse()
    return data
于 2010-05-20T23:15:00.063 回答
3

当您以下列方式定义属性时:

class Tree:
    root = None
    data = []

..该空列表对象是在 Python 定义类时创建的,而不是在您创建新实例时创建的。它是类属性,而不是实例属性。意思Tree.root是,在所有情况下都是同一个对象:

class Tree:
    root = None
    data = []

t1 = Tree()
t2 = Tree()

print id(t1.data) == id(t2.data) # is True, they are the same object

要获得您期望的行为,请将空列表的创建移至__init__函数,该函数仅在您创建新实例时调用,并且仅更改该实例(因为它分配给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

这个问题解释了为什么这种行为可能有用

于 2010-05-21T10:51:16.057 回答