3

我正在用 python 编写一个学习程序,但我没有得到我期望的行为。我正在尝试使用名为 node 的类创建一个非常基本的树。请不要因为我的树设计蹩脚而惩罚我,我只是想学习这门语言。

无论如何,我期待输出如下:

LEVEL1 0
LEVEL1 1

但是,我得到

LEVEL1 0
LEVEL1 1
LEVEL1 0 ... LEVEL2 0

在我做的那一行,leaves[0].addLeaf 我真的以为我会调用其中一个子叶的方法,但似乎我是从 TOP 叶调用的。请帮我理解。

不要被名字所欺骗traversePrint。什么都没有被遍历,反正还没有:(

#!/usr/bin/python

class node:
    """Something that can act like like leaves of a tree"""
    leaves = []
    def __init__(self, data=""):
        self.data = data
    def addLeaf(self, newNode="new"):
        self.leaves.append(node(newNode))
    def printLeafs(self):
        for leaf in self.leaves:
            print leaf.data
    def getLeafs(self):
        return self.leaves
    def traversePrint(self):
        for leaf in self.leaves:
            print leaf.data
        #for leaf in self.leaves:
        #   leaf.traversePrint()

top = node("TOP")
top.addLeaf("LEVEL1 0")
top.addLeaf("LEVEL1 1")

leaves = top.getLeafs()
leaves[0].addLeaf("LEVEL1 0 ... LEVEL2 0")

top.traversePrint()
4

3 回答 3

4

你的问题是,现在,leaves是一个类级别的属性。您希望它是实例级属性,以便列表不会在所有实例之间共享。有关差异的一些详细信息,请参阅此 SO question

幸运的是,创建leaves实例属性很容易:删除该行leaves = [],而是更改您的__init__方法以包含该行self.leaves = []

def __init__(self, data=""):
    self.data = data
    self.leaves = [] # Create a new list to hold this instance's children!

要更清楚地查看原始代码中发生了什么,请尝试在添加叶子后添加来编辑您的addLeaf方法。print([leaf.data for leaf in self.leaves])在您的原始代码中,这将打印出:

['LEVEL1 0']
['LEVEL1 0', 'LEVEL1 1']
['LEVEL1 0', 'LEVEL1 1', 'LEVEL1 0 ... LEVEL2 0']

当然,您只希望在第三个打印输出中显示一个叶子,因为您正在访问不同的节点,但您却得到了所有三个!这是因为当列表处于类级别时,所有实例node共享同一个leaves列表。当您在__init__方法内移动列表初始化时,您会看到三个addLeaf调用的预期结果:

['LEVEL1 0']
['LEVEL1 0', 'LEVEL1 1']
['LEVEL1 0 ... LEVEL2 0']
于 2013-09-18T23:20:57.440 回答
3

因为您leaves在类级别定义,所以所有实例node共享一个leaves列表。我怀疑那是你的意图。如果您希望每个node人都有自己的 leaves列表,则将作业移至__init__

    # leaves = [] # REMOVE THIS LINE
    def __init__(self, data=""):
        self.data = data
        self.leaves = []  # ADD THIS LINE

然后输出是:

LEVEL1 0
LEVEL1 1

并添加:

leaves[0].traversePrint()

印刷:

LEVEL1 0 ... LEVEL2 0

清除?

于 2013-09-18T23:28:57.293 回答
2

leaves是一个类属性,所以所有addLeaf要做的就是添加到该单个属性,因为所有节点都是类的对象node(顺便说一句,将其重命名为节点)

您想要的是每个节点属性叶,因此将其添加为实例属性,即__init__添加self.leaves = []

于 2013-09-18T23:22:01.317 回答