2012-02-22 59 views
3

當迭代器耗盡時,最後一次從迭代器返回某些東西的好方法是什麼?我使用的一個標誌,但是這是比較難看:從迭代器中返回,然後拋出StopIteration

class Example(): 

    def __iter__(self): 
     self.lst = [1,2,3] 
     self.stop = False # <-- ugly    
     return self 

    def next(self): 
     if self.stop: # <-- ugly 
      raise StopIteration 
     if len(self.lst) == 0: 
      self.stop = True    
      return "one last time" 
     return self.lst.pop() 

背景:我取字符串從外部來源未知量,並進一步發下來給調用者。當進程結束時,我想發出一個字符串「x記錄處理」。我無法控制調用代碼,所以這必須在我的迭代器中完成。

回答

5

你可以從__iter__產生,這將使它變成一個發電機功能(或者你可以只寫一個丹建議的發電機功能)。只是作爲警告,這可能會誤導濫用next方法的人。

class Example(): 

    def __iter__(self): 
     lst = [1,2,3] 
     for i in reversed(lst): 
      yield i 
     yield "one last time" 
4

也許你可以使用一個發電機函數:

def example(): 
    lst = [1, 2, 3] 
    while lst: 
     yield lst.pop() 
    yield 'one last time' 
+2

請記住,如果您無法或不想直接使用生成器,您可以將對象的__iter__方法本身作爲生成器函數。 – 2012-02-22 19:01:39

+0

謝謝,「收益」是我錯過的。 – georg 2012-02-22 19:18:24

0

你可以做這樣的事情:

class Example(): 
    def __iter__(self): 
     self.lst = [1, 2, 3] 
     return self 

    def next(self): 
     try: 
      return self.lst.pop() 
     except IndexError: 
      print "done iterating" 
      raise StopIteration 

>>> for i in Example(): 
... print i 
... 
3 
2 
1 
done iterating 

在您的實際代碼,你可能需要改變你的異常類型捕捉,但這種格式應該仍然適用。

1

不要返回一個額外的東西。這是一個壞主意,因爲它不能很好地延伸。如果你想要做總和以及計數呢?或哈希以及計數?迭代器是一個有狀態的對象。利用它。

class Example(collections.Iterator): 
    def __iter__(self): 
     self.lst = [1,2,3] 
     self.count = 0  
     return self 
    def next(self): 
     if self.lst: 
      self.count += 1 
      return self.lst.pop() 
     raise StopIteration() 

使用方法如下。

my_iter= iter(Example()) 
for item in my_iterprin: 
    print(item) 

print(my_iter.count) 
+0

我不能這樣做,因爲我不控制調用代碼(這是一個wsgi應用程序)。 – georg 2012-02-22 19:32:52

+1

我不控制調用代碼?這很少是真的。打電話給他們並與他們交談。 – 2012-02-22 19:43:47