【问题标题】:Is there such a thing as "too many yield statements" in python?python中是否存在“太多的yield语句”之类的东西?
【发布时间】:2010-02-24 23:45:11
【问题描述】:

如果列出目录并读取其中的文件,与返回目录中所有文件的列表相比,yield 的性能在什么时候开始恶化?

这里我假设一个有足够的 RAM 来返回(可能很大的)列表。

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 更快。

【问题讨论】:

  • 您是否有代码可以说明您的担忧?
  • @saidimu:我正在查看那个页面,但我看不到它在哪里说iglob() 更快。它说iglob() 返回它的结果“实际上并没有同时存储它们”,但这并不一定意味着任何关于性能的事情。
  • 我认为不必同时存储它们会对速度(和内存)产生积极影响?
  • @saidimu:你为什么会这么认为?你应该测量,因为它很容易使用 timeit: docs.python.org/library/timeit.html
  • @saidimu:“我在注释中内联代码时遇到问题”。切勿在您拥有的问题的评论中发布代码。这是你的问题。更新您的问题。不要在您已经拥有并且可以解决的问题上与 cmets 混淆。

标签: python yield


【解决方案1】:

进一步使用yield 不会导致性能下降。事实上,与在列表中组合事物相比,yield 实际上通过比较更多的元素来改进。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 谢谢。我在 os.listdir 和 os.walk 之间进行了辩论,但我认为这一点现在没有实际意义(从性能的角度来看)。更一般地说,是否存在过多产量成为问题的情况(例如,由于 python 的实现假设?)
    【解决方案3】:

    使用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
    

    【讨论】:

      【解决方案4】:

      在 Python 2.7 中,glob 的定义是

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-07
        • 1970-01-01
        相关资源
        最近更新 更多