2014-10-12 107 views
1

我試圖圍繞python生成器包裹我的頭,因此,我試圖打印使用yield的無限嵌套的對象,但我發現我仍然遇到吹出堆棧的問題。理想情況下,我希望能夠得到,當它走來打印每個項目,但我想不出我做錯了什麼:Python與發電機的無限遞歸

class Parent:  
    def __init__(self, name, child=None): 
     self._name = name 
     self._child = child 

    def get_name(self): 
     return self._name 

    def get_child(self): 
     return self._child 

    def set_child(self, child): 
     self._child = child 

    def __iter__(self): 
     next_child = self._child.get_child() 
     if not next_child: 
      raise StopIteration    
     else: 
      self._child = next_child 
      yield next_child 

    def __str__(self): 
     return "%s has %s" % (self._name, self._child) 

if __name__ == '__main__': 
    p1 = Parent("child") 
    p2 = Parent("child", p1) 
    p1.set_child(p2) 

    for t in p1: 
     print t 
+2

如果你讀了回溯,你會注意到,錯誤是由'打印t'引起的,因此,通過'Parent .__ str__',而不是'__iter__'。你自己設置好了 - 'p1'是'p2'的孩子,它是'p1'的孩子,它是'p2'的孩子,... – jonrsharpe 2014-10-12 14:53:58

回答

1

在你的代碼中的錯誤,如jonrsharpe注意,是由於__str__功能,它試圖返回:

child has child has child has child has child has ... 

你大概的意思是:

def __str__(self): 
    return "%s has %s" % (self._name, self._child.get_name()) 
    # return 'child has child' 

此外,__iter__應該是一個發生器功能。生成器函數需要包含一個循環以持續生成值。所以它應該是這樣的:

def __iter__(self): 
    next_child = self._child.get_child() 
    while next_child:    
     yield next_child 
     next_child = next_child.get_child() 
    # When the function ends, it will automatically raise StopIteration 

通過修改,您的代碼打印了無盡的線條child has child

另請參閱What does the yield keyword do in Python?瞭解有關生成器函數的更多信息。

0

無限遞歸發生在__str__函數。它與__iter__函數無關。

當你做print t時,它執行t._child.__str__,它依次執行t._child._child.__str__等等。

嘗試改變__str__函數定義像return self._name簡單的東西,你不會得到一個遞歸深度超過誤差