如何使用itertools模块构建"矢量化"构建块?

ovg*_*vin 4 python vectorization python-itertools

配方段itertools文档开始这样的文字:

扩展工具提供与底层工具集相同的高性能.通过一次处理一个元素而不是将整个迭代一次性地存储到存储器中来保持优异的存储器性能.通过以功能样式链接工具来保持代码量很小,这有助于消除临时变量.通过使用for循环和生成器而不是使用"矢量化"构建块来保留高速度,这会产生解释器开销.

问题是,如何构建发电机以避免开销?你能提供一些具有这种开销的构造不良的块的例子吗?

当我回答这个问题时,我决定问我在哪里无法确切地说是否chain(sequence, [obj])有超支chain(sequence, repeat(obj,1)),我应该更喜欢后者.

use*_*342 5

doc文本不是关于如何构造生成器以避免开销.它解释了正确编写的itertools代码,例如示例中提供的代码,完全避开for循环和生成器,将其留给itertools或内置收集器(如list)来使用迭代器.

举个例子,tabulate例如:

def tabulate(function, start=0):
    "Return function(0), function(1), ..."
    return imap(function, count(start))
Run Code Online (Sandbox Code Playgroud)

写这个的非矢量化方式应该是:

def tabulate(function, start=0):
    i = start
    while True:
        yield function(i)
        i += 1
Run Code Online (Sandbox Code Playgroud)

这个版本"会产生解释器开销",因为循环和函数调用是在Python中完成的.

关于链接单个元素,可以安全地假设chain(sequence, [obj])(通常)更快,因为使用专门的语法和操作码在Python中对固定长度列表构造进行了很好的优化.同样,chain(sequence, (obj,))甚至会更快,因为元组共享列表的优化,并且引导更小.与基准测试一样,测量python -m timeit比测量要好得多.

文档报价并没有在迭代器创建的差异,如通过选择一个展出关注自身repeat(foo, 1)[foo].由于迭代器只生成一个元素,因此它的消耗方式没有区别.在处理可产生数百万个元素的迭代器时,文档谈论处理器和内存效率.与此相比,选择创建更快的迭代器是微不足道的,因为创建策略可以随时更改.另一方面,一旦代码被设计为使用不向量化的显式循环,在没有完全重写的情况下稍后更改可能非常困难.