【问题标题】:Append function adds element to member of list附加函数将元素添加到列表成员
【发布时间】:2020-12-19 04:41:24
【问题描述】:

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

【问题讨论】:

    标签: python python-class


    【解决方案1】:

    在 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 []
    
    ...
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      猜你喜欢
      • 2018-09-12
      • 2017-04-16
      • 2012-10-26
      • 2014-06-10
      • 1970-01-01
      • 2017-06-23
      • 2014-06-16
      相关资源
      最近更新 更多