为什么这个Fizz Buzz生成器比这个Fizz Buzz Iterator类快得多?

时间:2014-02-08 17:57:14

标签: python performance iterator generator fizzbuzz

在了解迭代器类方法和生成器之后,我使用每个习语测试了简单的Fizz Buzz解决方案的性能特征:

>>> from timeit import timeit
>>> timeit('tuple(fizzbuzz.FizzBuzzIterator(10))', 'import fizzbuzz')
13.281935930252075
>>> timeit('tuple(fizzbuzz.fizz_buzz_generator(10))', 'import fizzbuzz')
7.619534015655518

根据timeit,生成器函数比迭代器类的快<1>快

我的问题:为什么这个Fizz Buzz生成器明显快于这个Fizz Buzz Iterator类?

Fizz Buzz迭代器类

class FizzBuzzIterator:

    def __init__(self, low, high=None):
        if high is None:
            self.high = low
            self.current = 1
        else:
            self.high = high
            self.current = max(low, 1)

    def __iter__(self):
        return self

    def next(self):
        if self.current > self.high:
            raise StopIteration
        else:
            c = self.current
            self.current += 1
            if (c % 5 + c % 3) == 0:
                return 'FizzBuzz'
            elif c % 5 == 0:
                return 'Buzz'
            elif c % 3 == 0:
                return 'Fizz'
            else:
                return str(c)

Fizz Buzz生成器功能

def fizz_buzz_generator(low, high=None):
    if high is None:
        high = low
        cur = 1
    else:
        cur = max(low, 1)
    while cur <= high:
        c = cur
        cur += 1
        if (c % 5 + c % 3) == 0:
            yield 'FizzBuzz'
        elif c % 5 == 0:
            yield 'Buzz'
        elif c % 3 == 0:
            yield 'Fizz'
        else:
            yield str(c)

1 个答案:

答案 0 :(得分:6)

因为很明显,生成器比迭代器更有效。

您的第一个解决方案具有以下有趣特征:

  1. 它使用对象。
  2. 对于 n 号码的迭代,调用 3 + n 方法并访问 2 + 4·n 属性可能会导致运营缓慢。
  3. 例外用于控制流程。
  4. 第二个解决方案不会执行这些操作,而是yield s,这意味着语言运行时执行繁重的工作。由于运行时通常以C语言实现,因此可以比第一个解决方案的高级代码更优化。

    接下来,您应该考虑您正在进行基准测试的。要获得良好的基准,您应该选择不同的输入尺寸 n ,并观察两种解决方案在不同尺度上的比较。

    • 对于非常小的 n ,我们预计初始化成本占主导地位。这与您的结果一致,因为执行函数调用比创建对象便宜。
    • 对于较大的 n ,我们期望算法的特征占主导地位。由于算法完全相同,因此图形应具有相同的形状。但是每次迭代,第一个解决方案的成本要高得多(四个属性访问,一个方法调用)。然后,这两种解决方案将是具有略微不同斜率的图形。每次迭代成本的确切关系只能通过获得许多输入大小 n 的许多时序的大数据集来评估,然后将函数拟合到该数据。