2013-02-21 40 views
0

在此代碼:Python 2.7版:奇怪的構造函數的行爲:改變錯誤的領域

# coding=utf-8 


def print_tree(node, tree=0): 
    print(u"|---" * tree + u"-> %s" % node) 
    for kid in node.children: 
     print_tree(kid, tree + 1) 


class Person(object): 
    parent = None 
    first_name = None 
    last_name = None 
    children = [] 

    def __str__(self): 
     return '%s %s' % (self.first_name, self.last_name) 

    def __unicode__(self): 
     return u'%s %s' % (self.first_name, self.last_name) 

    def __init__(self, first_name, last_name, parent=None): 
     if parent is not None: 
      if not isinstance(parent, Person): 
       raise AttributeError('`parent` is not `Person` type!') 
      self.parent = parent 
      self.parent.children.append(self) 
     self.first_name = first_name 
     self.last_name = last_name 
     #self.children = [] 


root = Person('Alan', 'Smith') 
p1 = Person('Barbara', 'Smith', root) 
p2 = Person('Basia', 'Smith', root) 
p3 = Person('Bary', 'Smith', root) 

print_tree(root) 

如果我刪除從#self.children = []例如評論工作正常。但我不明白爲什麼我必須添加這一行?

在調試器中我發現,線self.parent.children.append(self)增加self也爲self.children

爲什麼?

回答

1

在python中,當你在類級聲明一個屬性時,它使它成爲一個類屬性(在類的所有實例之間共享)。在你的情況下,你需要實例屬性。實例屬性必須在構造函數中創建(您的self.children = [])。

+0

Lol,3年的自學Python,bilion代碼行和你破壞了我的基本知識:D – WBAR 2013-02-21 15:35:28

+0

對不起;如果你使用過其他語言,這並不是非常明顯,但它是有意義的(班級屬性定義級別)。 – 2013-02-21 21:01:10

0

你有問題,因爲在你的代碼childrenclass variable(當你訪問它的類級別是指,而不是實例級別),而不是一個instance variable(這是每個實例是唯一的)。每次__init__您的Person實例

self.children = [] 

所以,你必須添加的東西等等。

0

您正在引用對象實例的子對象,因此您不能僅將它保留在Class作用域/圖層中。因此,你需要self.children = [],否則你不是指一個實例的孩子,而是班級'。 (而後者的語法是Person.children

+1

(2)不正確。他將「自我」添加到父母的「孩子」列表中,如果不是完全直觀的閱讀,這是完全有效的。 – 2013-02-21 15:29:48

+0

我的錯誤。我將刪除這部分答案。謝謝你的收穫! (這是我的問題:試着快速回答我的答案,錯過了一個重要的細節!) – BlackVegetable 2013-02-21 15:30:46

2

children是一個類屬性,你希望它是一個實例屬性。您應該從班級範圍中全部刪除children=[],並且只留下__init__方法中的那個。