为什么在这种特殊情况下使用生成器对象?

sha*_*wat 4 python list generator web-crawler

我正在查看从互联网上下载的一些代码.这是一个基本的webcrawler.我遇到了以下for循环:

for link in (links.pop(0) for _ in xrange(len(links))):
    ...
Run Code Online (Sandbox Code Playgroud)

现在,我觉得以下代码也可以工作:

for link in links:
    ....
links=[]
Run Code Online (Sandbox Code Playgroud)

研究,我发现第一个实例清除links并生成一个generator object (genexpr).links从不在for循环中使用,因此它的长度减小与代码无关.

使用xrange是否有任何特殊原因,每次弹出元素?即使用生成器对象而不是调用标准列表的元素是否有任何优势?此外,在什么情况下发电机是有用的; 为什么?

Gar*_*ees 6

很难看出你引用的代码有任何理由.

我唯一能想到的是,对象links可能很大,或者与稀缺资源相关联,因此尽快释放它们可能很重要(而不是等到循环结束才能释放所有对象) ).但是(a)如果是这样,最好在创建它时处理每个链接(可能使用生成器来组织代码),而不是在开始处理它之前构建整个链接列表; (b)即使您在处理之前别无选择,只能建立整个列表,清除每个列表条目比弹出列表要便宜:

for i, link in enumerate(links):
    links[i] = None
    ...
Run Code Online (Sandbox Code Playgroud)

(弹出带有n个项目的列表中的第一个元素需要O(n),尽管在实践中它会相当快,因为​​它是使用实现的memmove.)

即使你绝对坚持在遍历它时重复弹出列表,最好像这样编写循环:

while links:
    link = links.pop(0)
    ...
Run Code Online (Sandbox Code Playgroud)

  • 它更短,更清晰,因为操作更少,并且避免构造不必要的`xrange`和生成器对象.但每个人都有自己的品味,所以使用发电机版本并没有错. (3认同)