【问题标题】:Which is generally faster, a yield or an append?哪个通常更快,产量或附加?
【发布时间】:2011-03-30 02:29:58
【问题描述】:

我目前正在一个个人学习项目中阅读 XML 数据库。我发现自己正在编写收集数据的函数,但我不确定返回它们的快速方法是什么。

这通常更快:

  1. yields,或
  2. 函数中有几个append()s,然后是return,然后是list

我很高兴知道在什么情况下yields 会比append()s 更快,反之亦然。

【问题讨论】:

    标签: python performance return generator yield


    【解决方案1】:

    yield 具有懒惰的巨大优势,而速度通常不是使用它的最佳理由。但是,如果它在您的上下文中有效,那么没有理由不使用它:

    # yield_vs_append.py
    data = range(1000)
    
    def yielding():
        def yielder():
            for d in data:
                yield d
        return list(yielder())
    
    def appending():
        lst = []
        for d in data:
            lst.append(d)
        return lst
    

    这是结果:

    python2.7 -m timeit -s "from yield_vs_append import yielding,appending" "yielding()"
    10000 loops, best of 3: 80.1 usec per loop
    
    python2.7 -m timeit -s "from yield_vs_append import yielding,appending" "appending()"
    10000 loops, best of 3: 130 usec per loop
    

    至少在这个非常简单的测试中,yield 比 append 快。

    【讨论】:

    • lazy 是否意味着内存要求低
    • 我为 WKdm 算法编写了一个压缩器/解压缩器。在分析了一个将位解包到列表中的函数之后,速度最慢。我将它转换为发电机,它甚至更慢。 yield 版本提供了大约 22MB/s,append 版本提供了大约 38MB/s。所以它真的取决于你在做什么。
    • lst.append 查找可能会减慢appending() 的速度。您可以在循环外使用append = lst.append 进行尝试。
    【解决方案2】:

    我最近问自己一个类似的问题,探索通过附加到列表或通过生成器生成列表(或元组)的所有排列的方法,并发现(对于长度为 9 的排列,大约需要一秒钟左右生成):

    • 幼稚的方法(排列是列表,追加到列表,返回列表的列表)大约需要itertools.permutations的时间的三倍
    • 使用生成器(即yield)可以减少大约。 20 %
    • 使用生成器生成元组最快,大约是itertools.permutations的两倍。

    带一粒盐!计时和分析非常有用:

    if __name__ == '__main__':
        import cProfile
        cProfile.run("main()")
    

    【讨论】:

      【解决方案3】:

      TH4Ck 的 yield() 有一个更快的替代方法。这是列表理解。

      In [245]: def list_comp():
         .....:     return [d for d in data]
         .....:
      
      In [246]: timeit yielding()
      10000 loops, best of 3: 89 us per loop
      
      In [247]: timeit list_comp()
      10000 loops, best of 3: 63.4 us per loop
      

      当然,在不了解代码结构的情况下对这些操作进行微基准测试是相当愚蠢的。它们中的每一个在不同的情况下都很有用。例如,如果您想应用可以表示为单个表达式的简单操作,列表推导很有用。 Yield 具有显着优势,可以将遍历代码隔离到生成器方法中。哪个合适很大程度上取决于使用情况。

      【讨论】:

      • 我实际上想包含列表推导,但我在这两个之间进行选择:[n for n in func_that_yields()][n for n in func_that_returns_an_iterable()]。请注意,n 可以是简单的元素解包,也可以是复杂的逐元素操作。无论如何,你有好点:)
      【解决方案4】:

      首先你必须决定,如果你需要生成器,这也得到了改进的方法。像列表生成器“[elem for elem in somethink]”。如果您只是将列表中的值用于某些操作,则建议使用生成器。但是,如果您需要列表进行许多更改,并同时使用许多元素,则必须是列表。 (如果标准程序员使用列表的 70% 次,最好是生成器。使用更少的内存,只是很多人只是看不到其他的列表方式。不幸的是,在我们这个时代,很多人对良好的优化小便,只是为了工作.)

      如果你使用列表生成器来提高回报率,让我们对 yield 人做同样的事情。无论如何,我们为 Python 编程语言中的所有操作提供了多种更优化的方法。

      收益比回报快,我会证明这一点。 看看这些家伙:

      data = range(1000)
      
      def yielder():
          yield from data
      
      def appending():
          L = []
          app = list.append
          for i in data:
              app(L, i)
          return L
      
      def list_gen():
          return [i for i in data]
      

      当然追加会比其他想法慢,因为我们创建和扩展列表任何循环时间。只是循环“for”是非常不优化的,如果你可以避免这种情况,那就这样做。因为在任何一步,这个函数都会加载下一个元素并写入我们的变量,以便在内存中获取这个对象值。所以我们在任意元素处跳转,创建引用,循环扩展列表(声明的方法是极速优化器),当我们生成just return时,summary在两个列表中得到了2000个元素。

      list_gen 内存较少,我们只返回元素,但像 up 一样,我们生成第二个列表。现在我们得到了两个列表,原始数据和她的副本。摘要 2000 个元素。只是我们避免了创建对变量的引用的步骤。因为我们在列表中的 gen 避免了这一步。只写元素。

      yielder 使用最少的内存,因为我们刚刚从数据中得到了 yield 值。我们避免一个参考。例如:

      data = range(1000)
      
      def yielder():
          yield from data
      
      def list_gen():
          return [i for i in data]
      
      #Now we generate next reference after line [i for i in data]
      for i in list_gen():
          #some instruction
      
      #This is our first reference, becouse was yield from data.
      for i in yielder():
          #some instruction
      

      对某条指令仅使用一个元素,而不是全部来自列表,下一个值 yielder 将在下一个循环中返回,而不是存储所有 1000 个元素以写入参考。

      srry for little dig out topic,就在我不小心被谷歌搜索翻过来的时候,其他初学者的python程序员可以看到这个废话。

      【讨论】:

        猜你喜欢
        • 2011-12-07
        • 2012-07-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-07
        • 2010-11-10
        • 2012-10-03
        • 2011-02-15
        相关资源
        最近更新 更多