2016-11-17 7 views
0

から定義された配列属性へのアクセスは私のコードであるとき、私はシンプルなノードツリーを作るために抱き合わせている:再帰エラーそこでここでは、クラスレベル

class Node(object): 
    child = [] 
    def __init__(self,id): 
      self.id =id 
    def addChild(self,child): 
      self.child.append(child) 
    def printChildOnwards(self): 
      yield self.id 
      for x in self.child: 
        yield from x.printChildOnwards() 


firstChild = Node('1') 
secondChild = Node('2') 
thirdChild = Node('3') 
fourthChild = Node('4') 

firstChild.addChild(secondChild) 
firstChild.addChild(thirdChild) 


for x in firstChild.printChildOnwards(): 
    print(x) 

私はselfによって定義されたクラスレベルの属性にアクセスしました自分のバージョンにアクセスしていることを確認してください。

出力:1 2 3

この行動の背後にある理由は何ですか: 1 2 2 2 2 ... then recursion error max depth

私は単に__init__

self.child = [] このような出力の内部でそれを定義する場合、それは動作しますが?なぜそれを __init__に含める必要がありますか?単に printChildOnwards呼び出して

class Node(object): 

    child = [] 

    def __init__(self, id): 
     self.id = id 

child属性はNodeのすべての単一のインスタンスは、そのオブジェクトを共有することを意味しNodeクラス、上のクラスレベルの属性であり、これすべての反復されます:あなたの最初の例では

+1

サイドノート:Python 3を使用しているので( 'yield from'はそれを与えます)、' object'から明示的に継承する必要はありません。これはPython 2では(新しいスタイルのクラス動作を強制するために)必要ですが、Python 3ではすべてのクラスが「新しいスタイル」であり、 'object'から暗黙的に継承されています。 – ShadowRanger

+0

ありがとうございました! –

答えて

1

同じリストから印刷を続ける。見つけたとおり、__init__メソッドで定義すると、インスタンスごとにインスタンスレベルchildという属性が作成されるため、これらはすべて一意であり、同じ子の共有リストを反復することはありません。

id機能を使用すると、オブジェクトのID(メモリアドレス)を簡単に確認できます。それを使用すると、この例を使用して、子属性が同じであることを自分で見ることができます。

>>> n1 = Node(1) 
>>> n2 = Node(2) 
>>> id(n1.child) 
139928077828744 
>>> id(n2.child) 
139928077828744 

バック固定バージョンに周りにそれを変更する:

class Node(object):    
    def __init__(self, id):  
     self.child = []    
     self.id = id    

はもう一度id機能を使用して再度確認し、彼らが異なっていることを見てください。

>>> n1 = Node(1)            
>>> n2 = Node(2)                
>>> id(n1.child) 
139928077829192 
>>> id(n2.child) 
139928077828936 
+0

これは、クラス・レベルの属性を最初にinitで定義して、それらを互いにユニークにする必要があることを意味します。 –

+0

はい。私はちょうどこれをよりよく説明するために答えを更新しました。 – metatoaster

+0

ありがとうございました!病気を受け入れる –

関連する問題