Python初始化默认值创建类的链接实例

Python初始化默认值创建类的链接实例,python,list,python-3.x,graph,init,Python,List,Python 3.x,Graph,Init,此代码旨在创建一个图形实现。但是,所有节点“self.children”都链接到内存中的同一个列表,因此向其中任何节点添加子节点都会将其添加到所有节点。我一辈子都想不出为什么会发生这样的事情,我已经上过很多次这样的课了,没有过这样的问题 我的意思是,仅仅因为你在默认值中定义了一个列表并不意味着我就在那里创建了一个列表,是吗?这令人困惑 class DescisionNode(object): def __init__(self,data,score,childs=[]):

此代码旨在创建一个图形实现。但是,所有节点“self.children”都链接到内存中的同一个列表,因此向其中任何节点添加子节点都会将其添加到所有节点。我一辈子都想不出为什么会发生这样的事情,我已经上过很多次这样的课了,没有过这样的问题

我的意思是,仅仅因为你在默认值中定义了一个列表并不意味着我就在那里创建了一个列表,是吗?这令人困惑

class DescisionNode(object):
    def __init__(self,data,score,childs=[]):
        self.data = data
        self.score = score
        self.parent = None
        self.children = childs
    def getTop(self):
        if self.parent == None:
            return self
        else:
            return self.parent.getTop()
    def getEnds(self):
        out = []
        if len(self.children)==0:
            return [self]
        else:
            print(self,self.children)
            for n in self.children:
                out += n.getEnds()
            return out
    def add(self, newNode):
        if newNode.parent == None:
            newNode.parent = self
        else:
            raise Exception("Parent already exists.")
        if newNode is self:
            raise Exception("self may not be child")
        self.children.append(newNode)
这是由于:

Python的默认参数在定义函数时计算一次,而不是每次调用函数时(比如Ruby)。这意味着,如果您使用一个可变的默认参数并对其进行了变异,那么您将并且已经对该对象进行了变异,以便将来调用该函数

您可以在此处找到一些讨论:

这仅仅是因为Python中的函数是一级对象,而不仅仅是一段代码。 一旦你开始用这种方式思考,那么它就完全有意义了:函数是一个根据其定义求值的对象;默认参数是一种“成员数据”,因此它们的状态可能会从一个调用更改为另一个调用-与任何其他obje中的状态完全相同


考虑向前(下一个节点)构建列表要比向后(父节点)构建列表容易得多。虽然此链接可以回答问题,但最好在此处包含答案的基本部分,并提供链接供参考。如果链接页面发生更改,仅链接的答案可能无效。-用摘录编辑。非常感谢。