【问题标题】:Python init default values create linked instances of class [duplicate]Python init默认值创建类的链接实例[重复]
【发布时间】:2016-05-12 03:33:53
【问题描述】:

此代码旨在创建图形实现。但是,所有节点“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 list python-3.x graph init


【解决方案1】:

这是因为:http://docs.python-guide.org/en/latest/writing/gotchas/#mutable-default-arguments

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

您可以在这里找到一些讨论: "Least Astonishment" and the Mutable Default Argument

这仅仅是因为 Python 中的函数是一流的对象,而不仅仅是一段代码。 一旦你开始思考这种方式,那么它就完全有道理了:函数是一个根据其定义进行评估的对象;默认参数是一种“成员数据”,因此它们的状态可能会从一个调用更改为另一个调用 - 就像在任何其他对象中一样

【讨论】:

  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
  • 编辑摘录。谢谢。
猜你喜欢
  • 2012-05-08
  • 1970-01-01
  • 2021-05-16
  • 1970-01-01
  • 2015-11-07
  • 1970-01-01
  • 2019-03-22
  • 2013-09-07
  • 1970-01-01
相关资源
最近更新 更多