遍历可迭代类的开销

问题描述 投票:7回答:3

我只是在玩弄Python的生成器和可迭代的类。基本上,我想测试一下我从来不太确定的东西:Python中的类有一些开销,如果可能的话,最好依靠实现yield的方法,而不是实现迭代器协议的类。 >

我在Google上找不到关于此主题的令人满意的解释,所以我决定使用以下两个简单脚本对它们进行独立测试:func_iter.pyclass_iter.py

这里是func_iter.py

#!/usr/bin/env python

import time  

x = 0
def create_generator(num):
    mylist = range(num)
    for i in mylist:
        yield i

t = time.time()
gen = create_generator(100000)

for i in gen:
    x = x + i

print "%.3f" % (time.time() - t)

这里是class_iter.py

#!/usr/bin/env python

import time

x = 0

class Generator(object):

    def __init__(self, num):
        self.start = 0
        self.end = num

    def __iter__(self):
        return self

    def next(self):
        if self.start == self.end:
            raise StopIteration
        else:
            self.start = self.start + 1
            return self.start

t = time.time()
gen = Generator(100000)

for i in gen:
    x = x + i

print "%.3f" % (time.time() - t)

然后我在bash中使用它运行了10次(例如,对于class_iter.py:]

for i in {1..10}; do ./class_iter.py; done

这是它们的平均运行时间:

class_iter.py: 0.0864
func_iter.py: 0.0307

现在,我的问题是:

  1. 我的方法正确吗?我的比较公平吗?
  2. 如果是这样,为什么会有很大的不同?为什么class_iter.py花费的时间几乎是func_iter.py的三倍?
  3. 如果没有,如何改善方法或进行更好的比较?
  4. 编辑:如Dacav所建议,我还尝试使用func_iter.py而不是xrange运行range。这将其平均运行时间减少到0.0263秒。

我只是在玩弄Python的生成器和可迭代的类。基本上,我想测试一下我从未确定过的东西:Python中的类具有一些...

python performance benchmarking
3个回答
6
投票

类版本花费大量时间来访问其自己的变量。每个self.whatever都需要一个周期。如果将__iter__定义为生成器,并最小化实例变量的使用,则类和函数版本之间的差异可以忽略不计:


1
投票

如果您使用的是python,则很有可能您并非以软件性能为目标,而是更在意开发中的敏捷和敏捷。


1
投票

您似乎是完全正确的,您的比较是公正的。仅比较开销时,支持迭代器协议的类将比生成器函数慢。

© www.soinside.com 2019 - 2024. All rights reserved.