for循环和next方法迭代生成器,满足我的预期就OK了

Posted

技术标签:

【中文标题】for循环和next方法迭代生成器,满足我的预期就OK了【英文标题】:For loop and next method to iterate the generator, it is OK that fulfill my expectation 【发布时间】:2015-01-14 09:22:35 【问题描述】:

我测试了这些方法的性能:

def gen_iter():
    for _ in xrange(100000):
        yield _

def for_perf():
    it = gen_iter()
    for _ in it:
        pass

def next_perf():
    it = gen_iter()
    try:
        while True:
           _ = it.next()
    except StopIteration:
        pass

这些是测试结果(for_next_perf是模块名):

python -m timeit "from for_next_perf import for_perf; for_perf()"
100 loops, best of 3: 13.4 msec per loop

python -m timeit "from for_next_perf import next_perf; next_perf()"
10 loops, best of 3: 39 msec per loop

Line # Mem 使用增量行内容

 7    8.527 MiB    0.000 MiB   @profile
 8                             def for_perf():
 9    8.531 MiB    0.004 MiB       it = gen_iter()
10    8.582 MiB    0.051 MiB       for _ in it:
11    8.582 MiB    0.000 MiB           pass

Line # Mem 使用增量行内容

13    8.508 MiB    0.000 MiB   @profile
14                             def next_perf():
15    8.512 MiB    0.004 MiB       it = gen_iter()
16    8.562 MiB    0.051 MiB       while True:
17    8.562 MiB    0.000 MiB           try:
18    8.562 MiB    0.000 MiB               _ = it.next()
19    8.562 MiB    0.000 MiB               pass
20    8.551 MiB   -0.012 MiB           except StopIteration:
21    8.551 MiB    0.000 MiB               break

抱歉,我之前犯了一个错误,忘记为那个生成器循环。现在它满足了我的期望。 但是,我发现在我的工作中使用for_perf() 样式的运行时内存使用量正在增加。呵呵,可能是我的错,我应该再仔细测试一下我的代码。

【问题讨论】:

_ = it.next() 从生成器中获取第一个值,然后函数返回。当然它会比从生成器获取 all 值更快。 是的,您必须将while 带入try 【参考方案1】:

根据@vaultah 的评论,您正在比较两种不同的操作。您在第一个代码 sn-p 中完全使用了生成器,而在第二个代码中只从生成器对象中取出第一个元素。

def next_perf():
    it = gen_iter()
    while True:
        try:
            _ = it.next()
        except StopIteration:
            raise StopIteration
            # In working code you will break rather than re-raise.  Not sure how the time changes if you re-raise, I assumed it won't change too much (loop terminates either way), but that's a big assumption.

如果要执行与第一个相同的操作,第二个代码应该是这样的,并且几乎肯定会比其他版本花费更长的时间。

顺便说一句,yield _ 的做法真的很糟糕。仅将 _ 用于您实际上什么都不做的丢弃值。

【讨论】:

您希望while 循环 try 或使用breakStopIteration 被捕获时结束循环。无论哪种方式,您都不想再次引发异常。

以上是关于for循环和next方法迭代生成器,满足我的预期就OK了的主要内容,如果未能解决你的问题,请参考以下文章

21 迭代器生成器

迭代器和生成器

4.迭代器和生成器

知识总结和记录——迭代器和生成器

迭代器与生成器

迭代器与生成器