2011-12-16 19 views
1

を消費し、生産Pythonのコルーチンが、私は重複などの除去、クロールするURLのトラックを保持するクラスを持っている:鉱山のウェブクローラで

class VisitOnlyOnceClerk(object): 
    def __init__(self): 
     self.visited = set() 
     self.to_visit = set() 

    def enqueue(self, url, referer): 
     if not url in self.visited: 
      self.to_visit.add((url, referer)) 

    def __bool__(self): 
     return bool(self.to_visit) 

    def __iter__(self): 
     while self.to_visit: 
      (url, referer) = self.to_visit.pop() 
      self.visited.add(url) 
      yield (url, referer) 

これも値を持つことができる反復可能を提供それに追加されました:

clerk = VisitOnlyOnceClerk() 
clerk.enqueue(starting_point, starting_point) 
for (url, referer) in clerk: 
    # get the url, and clerk.enqueue() all the links from it ... 

これはコルーチンによって実行できるタスクのようです。私は価値を生み出すコルーチンの例を見てきましたが、価値を消費する例はありましたが、両方を行う例はありませんでした。何かのように:

def visit_once_clerk(): 
    visited = set() 
    to_visit = set([(yield)]) 

    for i in to_visit: 
     visited.add(i[1]) 
     extras = (yield i) 
     if extras: 
      to_visit.union(i for i in extras if i[1] not in visited) 

これはもちろん、私はそれがすべきだと思うように動作しません。コルーチンはここでも適切なツールですか?この場合、それらを使用する正しい方法は何ですか?

答えて

0

私はコルーチンここにあなたのクラスジェネレータの私見を移動するための方法は、Pythonのコルーチンは、あなたがすることができます方法よりもはるかに読みやすく、理解しやすく使いやすいへの道であるとは思いません。ここに私のポイントを作るために

は私がコルーチンを実装する方法を示します。

def visit_once_clerk(start_point=None): 
    visited = set() 
    to_visit = set(start_point or []) 

    while to_visit: 
     value = (yield to_visit.pop()) 
     if value and value not in visited: 
      to_visit.add(value) 

そして、ここではそれを使用する方法である。

clerk = visit_once_clerk(['start']) 
print clerk.next() # Print: start 
print clerk.send('test') # Print: test 
print clerk.next() # Raise StopIteration 

NB:あなたは差があることがわかります2つの実装の間に特別sendenqueue行動、価値を生み出すsendアクションは、新たな価値をスケジュールしますすぐ伊藤enqueueを送信します任意の歩留まり(setの使用による)

関連する問題