2011-12-25 138 views
4

我是相对较新的python(但不是编程),我不能解释以下行为。看起来,一个对象(“child”)中的一个变量(在我的示例中为“children”)正在被完全不同的对象(“node”)中该变量的值覆盖。为了给出一些上下文,我试图创建一个简单的Node类来在树结构中使用。节点有子节点和父节点(所有其他节点)。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.children和child.children具有相同的值(包含子列表),即使我只升级的节点。孩子。谢谢你的帮助!

回答

6

children变量被声明为一个类级别的变量,这样它的Node S的所有实例之间共享。您需要通过在初始化程序中设置实例变量来声明它。

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] 
+0

谢谢!我在教程中错过了这一点。 – cecomp64 2011-12-25 00:55:29

+0

这实际上与可变默认陷阱效果相同。变量本身不是共享的,但它的值是对可变内容的引用。因此,这些类级别的整数是安全的,但是因为列表是可变的,所以附加到列表中修改原始对象。 – tobyodavies 2011-12-25 01:44:04

+0

@tobyodavies它**是**“共享”,以至于它可以被看作是对象的一部分。每个Node实例都有一个'Node.parent'值,因为它属于类而不是单个实例。只是写入'node.parent'会创建一个单独的值,它是实例的一部分,并且在'node'内隐藏'Node.parent'(但它仍然可以作为child.parent访问)。 – 2011-12-25 04:50:58

2

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

取而代之,将其初始化为init类的方法。

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