【问题标题】:Python OOP and listsPython OOP 和列表
【发布时间】:2011-02-22 03:19:13
【问题描述】:

我是 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。

谢谢

【问题讨论】:

标签: python class-variables


【解决方案1】:

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

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

【讨论】:

  • 谢谢,没想到,将它们声明为类变量会使它们成为“全局”。现在终于可以完成我的作业了:)。
  • 在行尾写分号只是java和PHP的习惯,会删除它们:)
【解决方案2】:

将根和数据移动到 __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.dataself.data[:]可以包含相同的元素。我认为您的代码不需要复制这些元素,但如果是这种情况,您需要递归复制 self.data

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

【讨论】:

  • 感谢您关于复制列表的说明。这可能是我的下一个问题。
【解决方案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

This question 解释了为什么这种行为会很有用

【讨论】:

    猜你喜欢
    • 2022-01-06
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    • 2010-11-25
    • 2016-01-05
    • 2012-01-13
    • 2023-04-03
    • 1970-01-01
    相关资源
    最近更新 更多