Python向一个实例的列表添加元素时也会添加到另一个实例的列表中

5 投票
2 回答
13645 浏览
提问于 2025-04-17 13:39

可能重复的问题:
Python中的“最小惊讶”原则:可变默认参数

我创建了一个叫做Person的类,这个类有一个名字和一个孩子的列表。孩子们也是Person类的实例。如果我创建两个Person实例,并且在其中一个实例里添加一个孩子,这个孩子却会被添加到两个Person实例里。我本以为这个孩子应该只添加到person1的孩子列表里,而不是person2,但实际上它被添加到了两个实例里。我一定是哪里做错了,但我就是看不出来。

类似的问题中,有人提到把变量定义放在类里而不是构造函数里,但这不是我遇到的情况。任何帮助都非常感谢,这让我感到困惑!

下面是代码和输出:

class Person(object):

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

    def __repr__(self):
        return '<' + self.name + '>'

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


def main():
    person1 = Person('Person1')
    person2 = Person('Person2')

    person1.add_child(Person("Person 1's child"))

    print "Person 1's children:", person1.children
    print "Person 2's children:", person2.children

if __name__ == "__main__":
    main()

这段代码的输出是:

Person 1's children: [<Person 1's child>]
Person 2's children: [<Person 1's child>]

2 个回答

2

对于你的初始化,使用这个代替:

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

发生的情况是,这两个 Person 对象在后台使用的是同一个列表(这个列表是在函数定义的时候就绑定的,而不是在执行的时候)。你可以看看 这个问题,里面有更多的讨论。

11

这个问题出在children参数的默认值上。如果你使用一个可变对象(比如列表)并在函数头部初始化它,它只会初始化一次,然后在所有实例中都使用同一个对象。

这个问题在这里有讨论过。

试着把

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

替换成

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

撰写回答