Python 为什么这个FizzBuzz生成器要比这个FizzBuzz迭代器类快很多?
在学习了迭代器类方法和生成器之后,我使用每种习惯用法测试了简单的Fizz Buzz解决方案的性能特征:Python 为什么这个FizzBuzz生成器要比这个FizzBuzz迭代器类快很多?,python,performance,iterator,generator,fizzbuzz,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))'
>>> 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¾倍
我的问题是:为什么这个FizzBuzz生成器要比这个FizzBuzz迭代器类快很多
FizzBuzz迭代器类
嘶嘶声发生器功能
def嘶嘶声发生器(低、高=无):
如果“高”为“无”:
高=低
cur=1
其他:
电流=最大值(低,1)
而cur显然,生成器的实现效率高于迭代器
您的第一个解决方案具有以下有趣的特征:
它使用对象
对于n个数上的迭代,调用3+n方法并访问2+4.n属性,这两种操作都可能很慢
异常用于控制流
第二个解决方案不执行这些操作,而是产生s,这意味着语言运行库执行繁重的工作。由于运行时通常是用C实现的,因此这比第一个解决方案的高级代码优化得多
下一步,你应该考虑你真正的标杆管理。对于一个好的基准测试,您应该选择不同的输入大小n,并观察这两个解决方案在不同尺度下的比较
- 对于非常小的n,我们预计初始成本占主导地位。这与您的结果一致,因为执行函数调用比创建对象花费更少
- 对于较大的n,我们期望算法的特性占主导地位。由于算法完全相同,因此图形应该具有相同的形状。但每次迭代,第一个解决方案的成本要高得多(四个属性访问,一个方法调用)。然后,这两种解决方案将是斜率略有不同的图。每次迭代成本的精确关系只能通过获得大量输入大小n的大量计时数据集,然后对该数据拟合函数来评估
我绘制了一些图表,以查看绘制的线条有多大差异。这种可衡量的差异令人惊讶。再次感谢你的回答!感谢版主/管理员删除了离题答案:)
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)
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)