Python中有“过多的yield语句”这种说法吗?

4 投票
4 回答
533 浏览
提问于 2025-04-15 19:42

如果你在做一个文件夹的文件列表,并且要读取里面的文件,那么在什么情况下,使用“生成器”(yield)的方法性能会开始变差,相比于直接返回一个包含所有文件的列表呢?

在这里,我假设你的电脑有足够的内存来返回这个可能非常大的文件列表。

顺便说一下,我在评论中插入代码时遇到了一些问题,所以我会在这里放一些例子。

def list_dirs_list():
    # list version
    return glob.glob(/some/path/*)

def list_dirs_iter():
    # iterator version
    return glob.iglob(/some/path/*)

实际上,这两种调用方式都使用了os.listdir,所以在性能上看起来是一样的。但是这份Python文档似乎暗示使用glob.iglob会更快。

4 个回答

1

使用yield的效果和写一个函数对象类差不多,从实现和性能的角度来看也是如此。只是使用yield可能会比自己写的类中的__call__方法调用得更快,因为yield是直接在生成器的C语言实现中内置的。

为了更清楚地说明这一点,下面的用法和大致实现是一样的:

def generator_counter():
    i = 0
    while True:
        i += 1
        yield i

class functor_counter():
    def __init__(self):
        self.i = 0
    def __call__(self):
        i += 1
        return i
5

使用yield没有哪个时刻会导致性能下降。实际上,跟把所有东西放在一个列表里相比,使用yield的效果会更好,尤其是当元素数量增加的时候。

2

这要看你是怎么列出目录的。大多数情况下,Python会把整个目录的内容都放到一个列表里;如果是这样的话,即使你只用了一次“yield”,也是浪费。如果你使用的是 opendir(3),那么根据XKCD对“随机”的定义,它可能就是一个随机的数字。

撰写回答