在我的一个网络爬虫中,我有一个类,它跟踪要抓取的urls,删除重复的urls,等等:
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)当然,这并不像我认为的那样工作。协程在这里甚至是正确的工具吗?在这种情况下,使用它们的正确方式是什么?
发布于 2011-12-17 01:13:36
我不认为在这里使用协程的方式,你的类生成器IMHO比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注意:您可以看到这两个实现之间存在差异,特别是send和enqueue操作,send操作将产生立即发送的值ITOH enqueue将调度新值为随机产生(因为使用了set)
https://stackoverflow.com/questions/8537375
复制相似问题