这是相反的 什么你可以使用Python发电机的功能吗?:蟒蛇的发电机,发电机的表达, itertools 模块一些我最喜欢的蟒蛇,这些天。他们特别有用当设置了链条的操作,以执行上一大堆的数据--我经常使用他们的时候处理了文件。

因此,当它是 一个很好的时间使用发电机,或是发电机的表达,或 itertools 功能?

  • 当我应该喜欢 zip()itertools.izip(), 或
  • range()xrange(), 或
  • [x for x in foo](x for x in foo)?

显然,我们最终需要"解决"发电机转化为实际的数据中,通常通过创建一个清单或迭代过它与非发电机的循环。有时候我们只需要知道的长度。这不是我在问什么。

我们使用发电机,以便我们不是在指定新的列入存储器,用于临时数据。这特别意义的大数据集。它是有意义的小数据集的吗?是否有一个明显的存储器/cpu贸易?

我特别感兴趣,如果任何人已经做了一些分析在这,光的眼睛-开讨论 列表的理解与性能地图()及过滤器(). (alt链接)

有帮助吗?

解决方案

使用一个清单,而不是一个发生时:

1)需要访问的数据 倍(即缓的结果,而不是他们重新计算):

for i in outer:           # used once, okay to be a generator or return a list
    for j in inner:       # used multiple times, reusing a list is better
         ...

2)你需要的 随机存取 (或者任何访问比前顺序):

for i in reversed(data): ...     # generators aren't reversible

s[i], s[j] = s[j], s[i]          # generators aren't indexable

3)你需要 加入 串(这需要两个传过来的数据):

s = ''.join(data)                # lists are faster than generators in this use case

4)您使用 PyPy 这有时候不可以优化发电机的代码一样,因为它可以与正常功能的电话和名单操作。

其他提示

在一般情况下,不要使用发电机的时候你需要的清单的操作,如len(),颠倒()等等。

还可能有时候你不想懒惰的评估(例如做所有的计算,所以你可以释放资源)。在这种情况下,清单的表达可能会更好。

配置文件,档案,配置文件。

分析代码是唯一的办法知道如果你在做什么有任何效果的。

大多数用途的xrange、发电机等是静态的大小,小的数据集。只有当你得到较大的数据集,它真的有差别。范围()vs.xrange()大多只是问题的代码你看一个小小的更丑陋的,且不会失去任何东西,并且可能获得的东西。

配置文件,档案,配置文件。

你应该从不赞成 zipizip, rangexrange, 或者列推导在解析发电机.在Python3.0 rangexrange-喜欢的语义和 zipizip-像是语义。

列表解析实际上是清晰的像 list(frob(x) for x in foo) 对于那些有时你需要一个实际的列表。

如你所说,"这特别意义的大型数据集",我想这回答了你的问题。

如果你没有击中任何墙壁、绩效明智的,你仍然可以坚持到清单和标准的功能。那么当你遇到的问题表现出的开关。

如前所述通过@u0b34a0f6ae的意见,但是,使用发电机组在开始可以使它更容易的规模较大的数据集。

关于性能:如果使用psyco,列出可以相当的速度比发电机。在例如下面列出了几乎50%的速度时采用psyco.全()

import psyco
import time
import cStringIO

def time_func(func):
    """The amount of time it requires func to run"""
    start = time.clock()
    func()
    return time.clock() - start

def fizzbuzz(num):
    """That algorithm we all know and love"""
    if not num % 3 and not num % 5:
        return "%d fizz buzz" % num
    elif not num % 3:
        return "%d fizz" % num
    elif not num % 5:
        return "%d buzz" % num
    return None

def with_list(num):
    """Try getting fizzbuzz with a list comprehension and range"""
    out = cStringIO.StringIO()
    for fibby in [fizzbuzz(x) for x in range(1, num) if fizzbuzz(x)]:
        print >> out, fibby
    return out.getvalue()

def with_genx(num):
    """Try getting fizzbuzz with generator expression and xrange"""
    out = cStringIO.StringIO()
    for fibby in (fizzbuzz(x) for x in xrange(1, num) if fizzbuzz(x)):
        print >> out, fibby
    return out.getvalue()

def main():
    """
    Test speed of generator expressions versus list comprehensions,
    with and without psyco.
    """

    #our variables
    nums = [10000, 100000]
    funcs = [with_list, with_genx]

    #  try without psyco 1st
    print "without psyco"
    for num in nums:
        print "  number:", num
        for func in funcs:
            print func.__name__, time_func(lambda : func(num)), "seconds"
        print

    #  now with psyco
    print "with psyco"
    psyco.full()
    for num in nums:
        print "  number:", num
        for func in funcs:
            print func.__name__, time_func(lambda : func(num)), "seconds"
        print

if __name__ == "__main__":
    main()

结果:

without psyco
  number: 10000
with_list 0.0519102208309 seconds
with_genx 0.0535933367509 seconds

  number: 100000
with_list 0.542204280744 seconds
with_genx 0.557837353115 seconds

with psyco
  number: 10000
with_list 0.0286369007033 seconds
with_genx 0.0513424889137 seconds

  number: 100000
with_list 0.335414877839 seconds
with_genx 0.580363490491 seconds

尽可能表现感到关切的是,我不能想到的任何时候,你会想到使用一个单一发电机。

我从来没有找到一种情况,发电机就会妨碍你想要什么做的。然而,有大量的情况下使用的发电机将不会帮助你的任何多于不使用它们。

例如:

sorted(xrange(5))

不提供任何改善:

sorted(range(5))

你应该喜欢列表解析的,如果你需要保持的价值观周围的其他东西后来和你设置是不是太大。

例如:你是创造一个列表中,将循环过几次,后来在您的节目。

某种程度上可以认为发电机作为替代迭代的(环)与列表解析作为一种类型的数据结构的初始化。如果你想保持数据的结构,然后使用列表解析.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top