0

如何在不修改其成员的情况下将 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
4

2 回答 2

3

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

def __init__(self, name, type, children=None):
    self.name = name
    self.type = type
    self.children = children if children else []
于 2020-08-31T03:46:36.683 回答
3

在 Python 中为函数定义参数时,您偶然发现了一个非常常见的问题。这里有一个很好的解释。

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

...
于 2020-08-31T03:50:07.760 回答