2017-08-23 25 views
2

我想鏈接迭代器一起從一個主文件讀取一個迭代器和另一個迭代器取主文件的每一行,並根據第一個輸出處理另一個文件。如何「鏈」迭代器?

,我有如下

class MasterReader(object): 

    def __init__(self, filename): 
     self.f = open(filename, "r") 

    def __iter__(self): 
     return self 

    def __next__(self): 
     line = self.f.readline().strip() 
     if line == "": 
      raise StopIteration 
     return line 


class SubReader(object): 

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

    def __iter__(self): 
     self._next() 
     return self 

    def _next(self): 
     self.current = open(self.mr.__next__(), "r") 

    def __next__(self): 
     while True: 
      line = self.current.readline().strip() 
      if line == "": 
       self._next() 
       continue 
      return line 


mr = MasterReader("master") 
sr = SubReader(mr) 

for line in sr: 
    print(line) 

哪裏master是包含的其他文件

file1 
file2 

file1行的文件包含

1.a 
1.b 
1.c 

file2工作代碼包含

2.a 
2.b 
2.c 

輸出是

1.a 
1.b 
1.c 
2.a 
2.b 
2.c 

再次我有什麼作品,但感覺這是不對我有一個while迴路__next__我有手動檢查每個子文件和明確的結束調用master文件中的下一行。

是否有更好/更pythonic的方式做到這一點?

編輯: 這是我試圖完成的簡化問題。在真實版本中SubReader將會被穿線,而我只想要一個MasterReader。實際上,這對我的線程項目不起作用,但要確保在深入陷入混亂之前對迭代器進行概括。

+0

你試過'itertools.chain'嗎? –

+0

@PaulRooney我看着那個,但看起來它會處理第一個迭代器,然後處理第二個迭代器。我需要第一個迭代器的第一個元素,然後根據第一個迭代器的第一個元素。然後第一次然後是第二次。不過我會再看看'chain'。 – Jeff

+1

它很長(有三部分),但這個pycon視頻可能是有趣的... [一個關於協程和併發的奇怪課程](http://pyvideo.org/pycon-us-2009/pycon-2009-- a-curious-on-coroutines-and-co.html) - 這裏有一些生產者/消費者的例子。 – wwii

回答

1

由於文件對象本身是一個迭代器,你不一定需要在這兩種情況下實現__next__,只是產量從它線在你__iter__。更何況,讀取與文件爲循環隱式處理EOF:

class MasterReader(object): 
    def __init__(self, filename): 
     self.f = open(filename) 

    def __iter__(self): 
     for line in self.f: 
      yield line.strip() 
     self.f.close() 


class SubReader(object): 
    def __init__(self, mr): 
     self.mr = mr 

    def __iter__(self): 
     for filename in mr: 
      with open(filename) as f: 
       for line in f: 
        yield line.strip() 
+0

屈服而不是返回使所有的區別。 – wwii

1

你可以使用itertools.chain.from_iterable小功能的幫助下,得到每個文件剝離線。

from itertools import chain 

def fgen(fname): 
    with open(fname) as f: 
     for line in f: 
      yield line.strip() 

for a in chain.from_iterable(fgen(line) for line in fgen('master.txt')): 
    print(a)