使用生成器表达式而非列表的sorted()
在这里看到的讨论让我产生了好奇:Python - 生成时间差。我最开始也以为生成器比列表要快,但在使用sorted()的时候,我就不太确定了。把生成器表达式传给sorted(),比传一个列表有什么好处呢?难道在排序之前,生成器表达式会被转换成列表吗?
补充说明:我很遗憾只能接受一个答案,因为我觉得很多回复都帮助我更好地理解了这个问题。再次感谢大家。
8 个回答
15
要对一组数据进行排序,必须先知道这组数据里的所有元素。因此,如果你把一个生成器传给 sorted()
函数,它会把生成器里的所有数据都用完。
19
最简单的方法来看看哪个更快,就是使用 timeit
。它告诉我,传递一个列表比传递一个生成器要快:
>>> import random
>>> randomlist = range(1000)
>>> random.shuffle(randomlist)
>>> import timeit
>>> timeit.timeit("sorted(x for x in randomlist)",setup = "from __main__ import randomlist",number = 10000)
4.944492386602178
>>> timeit.timeit("sorted([x for x in randomlist])",setup = "from __main__ import randomlist",number = 10000)
4.635165083830486
还有:
>>> timeit.timeit("sorted(x for x in xrange(1000,1,-1))",number = 10000)
1.411807087213674
>>> timeit.timeit("sorted([x for x in xrange(1000,1,-1)])",number = 10000)
1.0734657617099401
我认为这是因为当 sorted()
函数把传入的值转换成列表时,对于已经是列表的东西,它能更快地完成这个操作,而对于生成器就没那么快了。源代码似乎也证实了这一点(不过我只是看了评论,并没有完全理解所有的内容)。
48
首先,sorted()
这个函数会把你给的数据转换成一个列表。简单来说,它在检查参数有效性后,第一行代码就是这么做的。
newlist = PySequence_List(seq);
你可以查看Python 2.7的完整源代码和Python 3.1.2的完整源代码。
编辑:正如aaronasterling的回答所指出的,变量newlist
实际上是一个新的列表。如果传入的参数已经是一个列表,它会被复制一份。所以,使用生成器表达式的好处是可以节省内存。