Python中有“太多的yield语句”吗?

Python中有“太多的yield语句”吗?

问题描述:

如果执行一个目录列表并读取其中的文件,与返回目录中所有文件的列表相比,yield的性能开始恶化的几点?Python中有“太多的yield语句”吗?

在这里我假设一个有足够的内存来返回(可能是巨大的)列表。

PS我在注释中遇到内嵌代码的问题,所以我会在这里提供一些示例。

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

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

幕后调用glob使用os.listdir,所以看起来它们在性能上是等效的。但this Python doc似乎暗示glob.iglob更快。

+1

你有代码可以分享这可能说明你的关注? – 2010-02-25 00:01:58

+0

@saidimu:我正在看那个页面,但是我看不到它说'iglob()'更快。它说'iglob()'返回结果*“而不是实际同时存储它们”*但这并不意味着性能方面的任何暗示。 – 2010-02-25 00:53:42

+0

我会假设不必同时存储它们都具有正面的速度(和内存)影响? – saidimu 2010-02-25 01:00:33

这取决于你如何做目录列表。 Python中的大多数机制将整个目录列表拖入列表中;如果这样做,那么即使是单一产量也是浪费。根据XKCD对“random”的定义,如果使用opendir(3),那么它可能是一个随机数。

+0

谢谢。 我在os.listdir和os.walk之间进行了辩论,但我认为这一点现在没有意义(从性能的角度来看)。 更一般地说,是否有太多产量成为问题的情况(例如,由于python的实现假设?) – saidimu 2010-02-25 00:03:07

+0

当然没有想到的东西。 – 2010-02-25 00:06:11

yield的进一步使用导致性能下降没有意义。实际上,与汇总列表相比,yield实际上通过比较存在的更多元素而得到提高。

使用yield在功能上类似于编写仿函数类,即使从实现或性能的角度来看,除了它可以实际上比自创类上的__call__方法实际上更快地调用生成器,因为这是内置于生成器的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 

在Python 2.7,中glob的定义是

def glob(pathname): return list(iglob(pathname))

所以至少这个版本,glob永远不会比iglob更快。