2011-12-25 275 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 = [] 
    ...