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

recipe section的itertools文档以本文开头:

The extended tools offer the same high performance as the underlying
toolset. The superior memory performance is kept by processing
elements one at a time rather than bringing the whole iterable into
memory all at once. Code volume is kept small by linking the tools
together in a functional style which helps eliminate temporary
variables. High speed is retained by preferring “vectorized” building
blocks over the use of for-loops and generators which incur
interpreter overhead.

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

我决定问我什么时候回答this question,我无法确切地说链(序列,[obj])是否有超过链的开销(序列,重复(obj,1)),我应该更喜欢后者.

解决方法:

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

举例来说,制表示例:

def tabulate(function, start=0):
    "Return function(0), function(1), ..."
    return imap(function, count(start))

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

def tabulate(function, start=0):
    i = start
    while True:
        yield function(i)
        i += 1

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

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

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

上一篇:这个python代码可以更高效吗?


下一篇:python中的itertools模块