【问题标题】:Python - unusual behaviour with custom treePython - 自定义树的异常行为
【发布时间】:2014-07-31 23:42:39
【问题描述】:

我需要通过在 Python 脚本中使用树以非常特定的方式对列表进行排序,因此我编写了自己的快速 TreeNode 类。但是,在将子节点附加到节点时,我发现了非常奇怪的行为,我真的无法理解发生了什么。

这是课程:

class TreeNode:

    children = []
    identity = ""

    def __init__(self, node_id, c = []):
        self.identity = node_id
        self.children = c

    def get_id(self):
        return self.identity

    def append_child(self, child):
        self.children.append(child)

    def remove_child(self, child):
        self.children.remove(child)

    def get_children(self):
        return self.children

    def walk(self):
        yield self
        for child in self.children:
            for n in child.walk():
                yield n

    def find_id(self, node_id):
        if self.identity == node_id:
            return self
        for child in self.children:
            found = child.find_id(node_id)
            if found:
                return child
        return None

发生的情况是,当我将一个子项附加到树时,子项的子项列表被实例化为长度为 1,并且第一个元素是对同一个子项的引用。因此,子元素中的第一个元素也有一个长度为 1 的子元素列表,也指向同一个节点,并且它似乎无限地继续下去。

这是仅将单个元素附加到根节点后的“树”的可视化...

我不知道这里发生了什么,我希望其他更熟悉 Python 的人能够启发我。整个下午都在烦我!

【问题讨论】:

  • c = [] 中的 __init__ 看起来很可疑。你熟悉“Default Mutable Argument”陷阱吗?
  • 我不是。我现在用谷歌搜索一下。
  • 你能分享你如何创建一个孩子的代码吗?

标签: python list tree


【解决方案1】:
def __init__(self, node_id, c = []):

问题是你的c = []。函数的默认参数在 Python 中只计算一次。因此,第一次初始化 TreeNode 并更改 c 时,c 将在下次创建新 TreeNode 时保留更改后的值,因为它是一个列表,它们不会每次都创建新列表,它们会只是继续参考完全相同的列表。您将使用与父节点相同的 child 列表初始化子节点。

这正是你想要的:

def __init__(self, node_id, c = None):
    if c is None:
        c = []

这是因为每次初始化 TreeNode 时都会创建一个新的空列表。在之前的设置中,由于 Kevin 在他的评论中链接到的问题,您每次都在修改完全相同的列表。

【讨论】:

  • 谢谢,这解决了。对我来说完全是新问题。总是有新东西要学!我会尽快接受。虽然也许应该归功于凯文。
  • @Luke Python 充满了这样的复杂性;我最近才知道这个问题,可能是几天前,所以你并不孤单。
猜你喜欢
  • 2014-03-14
  • 1970-01-01
  • 1970-01-01
  • 2020-04-08
  • 1970-01-01
  • 2021-12-13
  • 1970-01-01
  • 1970-01-01
  • 2014-02-04
相关资源
最近更新 更多