Python堆栈损坏?

Python堆栈损坏?,python,Python,我对python(但不是编程)比较陌生,无法解释以下行为。似乎来自一个对象(“子对象”)的变量(在我的示例中是列表“子对象”)正在被完全不同的对象(“节点”)中该变量的值覆盖。为了提供一些上下文,我尝试创建一个简单的节点类,以便在树结构中使用。该节点具有子节点和父节点(所有其他节点) 我不明白为什么child.children会得到与node.children相同的值。它们是否以某种方式引用了相同的数据?为什么?代码和输出如下: class Node: children = []

我对python(但不是编程)比较陌生,无法解释以下行为。似乎来自一个对象(“子对象”)的变量(在我的示例中是列表“子对象”)正在被完全不同的对象(“节点”)中该变量的值覆盖。为了提供一些上下文,我尝试创建一个简单的节点类,以便在树结构中使用。该节点具有子节点和父节点(所有其他节点)

我不明白为什么child.children会得到与node.children相同的值。它们是否以某种方式引用了相同的数据?为什么?代码和输出如下:

class Node:
    children = []
    parent = 0
    visited = 0
    cost = 0
    position = (0, 0)
    leaf = 0

    def __init__(self, parent, pos):
        self.parent = parent
        self.position = pos

    def addChild(self, node):
        self.children += [node]

node = Node(0, (0,0))
child = Node(node, (3,2))

node.addChild(child)

print "node: ",
print node

print "node.childen: ",
print node.children

print "child: ",
print child

print "child.children",
print child.children
输出:

node:  <__main__.Node instance at 0x414b20>
node.childen:  [<__main__.Node instance at 0x414b48>]
child:  <__main__.Node instance at 0x414b48>
child.children [<__main__.Node instance at 0x414b48>]
节点:
node.childen:[]
儿童:
child.children[]

如您所见,node.children和child.children具有相同的值(包含child的列表),即使我只更新了node.children。谢谢你的帮助

您已将“children”作为类属性,这意味着它在该类的所有对象之间共享

相反,在类的init方法中初始化它

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

children
变量已声明为类级变量,因此它在
节点的所有实例中共享。您需要通过在初始值设定项中设置它来将其声明为实例变量

class Node:
    #children = [] # not here...
    parent = 0     # might want to rethink where you initialize these
    visited = 0
    cost = 0
    position = (0, 0)
    leaf = 0

    def __init__(self, parent, pos):
        self.parent = parent
        self.position = pos
        self.children = [] # ...but here

    def addChild(self, node):
        self.children += [node]

这实际上与可变默认gotcha的效果相同。变量本身不是共享的,但其值是对可变内容的引用。因此,这些类级整数是安全的,但由于列表是可变的,因此添加到列表后会修改原始对象。@tobyodavies它是“共享的”,甚至可以将其视为对象的一部分。每个
节点
实例都可以访问一个
节点.parent
值,因为它属于类而不是单个实例。只是写入
节点。parent
会创建一个单独的值,该值是实例的一部分,并隐藏
节点中的
节点。parent
节点中(但它仍然可以作为
子级。parent
访问)。所有这些变量都应该在
初始化中设置,而不是在类级别设置,因为它们在逻辑上是单个实例的一部分。Python不是Java(或C++或C.java):Python遵循的是在“代码>类< <代码>块内直接声明的一致规则……属于类(因此不属于实例)。@KarlKnechtel correct---只有一个对象,但有
n+1
对它的单独引用,每个节点实例一个,类本身一个。这是最正确的按值复制描述,其中值是对对象的引用(与python和java以及许多其他语言的调用约定相同)。我的观点是引用被复制到实例--
Klass.x
Klass().x
as不是同一个变量,尽管它们可能是对同一对象的单独引用(默认情况下也是如此)。我试图避免评论“应该”初始化什么的风格问题。