Append 函数将元素添加到列表的成员

Append function adds element to member of list

如何在不修改其成员的情况下将 Class 对象附加到列表?

class Node:
    def __init__(self, name, type, children=[]):
        self.name = name
        self.type = type
        self.children = children

    def add_child(self, child_node):
        self.children.append(child_node)

    def printNode(self, indent = 0):
        print(self.name + " has children " + str(len(self.children)))
        #for child in self.children: print(child, indent + 4)
            
if __name__ == "__main__":
    A = Node("A", "company")
    B = Node("B", "department")
    B.printNode()
    A.add_child(B)
    B.printNode()

append() 函数将节点 B 添加到自身,即使它应该只将它添加到节点 A 的子列表中,从输出中可以明显看出

B has children 0
B has children 1

切勿使用可变数据(例如列表)作为默认参数。像这样重新定义您的构造函数,它将按预期工作

def __init__(self, name, type, children=None):
    self.name = name
    self.type = type
    self.children = children if children else []

您在 Python 中定义函数参数时遇到了一个非常常见的陷阱。有一个很好的解释here

当您定义函数时,Python 解释器将创建用作默认参数的值。这些默认值然后用于每个函数调用。在这种情况下,解释 __init__ 时会创建空列表 children=[]。然后每次调用 add_child() 时都会使用相同的列表,无论调用哪个对象。

这是一个例子:

def my_func(a_list=[]):
    a_list.append("something")
    print(a_list)

>>> my_func()
["something"]
>>> my_func()
["something", "something"]

在这种情况下,a_list 在每次函数调用时都会重复使用,并且大小会继续增长。

解决这个问题的方法是使用不同的值来表示节点应该以一个空的子节点列表开始。像这样:

class Node:
    def __init__(self, name, type, children=None):
        self.name = name
        self.type = type
        self.children = children or []

...