2016-06-13 48 views
6

所以我从官方文档中得到了这些例子。 https://docs.python.org/2/library/timeit.html列表与发电机理解速度加入功能

什么使第一个例子(发生器表达式)比第二个(列表理解)慢?

>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000) 
0.8187260627746582 
>>> timeit.timeit('"-".join([str(n) for n in range(100)])', number=10000) 
0.7288308143615723 
+0

查看雷Hettinger的答案在这里http://stackoverflow.com/questions/9060653/list-comprehension-without-python –

+0

@BhargavRao - 虽然我同意雷蒙德的答案确实解决了这个问题,这个问题是根本不同于_that_题。 (在这里,OP想知道为什么list-comp更快 - 在另一个问题中,OP甚至不知道生成器或列表comp之间的区别)。我想我不确定什么政策应该是在这样的情况下带来这种情况下的应对...... – mgilson

+1

@mgilson另一个问题是这个问题的超级集合。在meta上有一篇文章说明我们可以投票结束,作为一个更广泛问题的重复。就像例如关闭*我如何将它转换为列表理解*作为*列表的复本,它是如何工作的*。有人试图创建更广泛的问题来帮助Ops(看看[cannon](http://sopython.com/canon/))。总而言之,如果某个问题已经在别的地方得到解答,那么我们就这样结束了。 (我反对描述说*确切的重复*对于锤子而不是正常的有答案) –

回答

9

str.join方法其迭代参数转换成一个列表,如果它不是一个列表或元组了。这使得连接逻辑可以多次迭代项目(它使得一次传递计算结果字符串的大小,然后第二次传递实际复制数据)。

您可以在the CPython source code看到:

PyObject * 
PyUnicode_Join(PyObject *separator, PyObject *seq) 
{ 
    /* lots of variable declarations at the start of the function omitted */ 

    fseq = PySequence_Fast(seq, "can only join an iterable"); 

    /* ... */ 
} 

的C API中的PySequence_Fast功能不正是我所描述的。它将任意迭代转换为列表(实质上通过调用list),除非它已经是列表或元组。

将生成器表达式转换为列表意味着生成器的通常优势(较小的内存占用空间和短路可能性)不适用于str.join,因此(小)附加开销发电机使其性能变差。