python -m timeit "tuple(xrange(600000))"
100个循环,最佳3:每循环11.5毫秒
python -m timeit "list(xrange(600000))"
100个循环,最佳3:每循环10.1毫秒
将它们与dis
模块进行比较:
>>> from dis import dis
>>> dis(lambda: tuple(xrange(600000)))
0 LOAD_GLOBAL 0 (tuple)
3 LOAD_GLOBAL 1 (xrange)
6 LOAD_CONST 1 (600000)
9 CALL_FUNCTION 1
12 CALL_FUNCTION 1
15 RETURN_VALUE
>>> dis(lambda: list(xrange(600000)))
0 LOAD_GLOBAL 0 (list)
3 LOAD_GLOBAL 1 (xrange)
6 LOAD_CONST 1 (600000)
9 CALL_FUNCTION 1
12 CALL_FUNCTION 1
15 RETURN_VALUE
答案 0 :(得分:3)
由于迭代器通常不会为您提供前端大小,因此元组和列表都需要使用过度分配策略来处理任意大小的迭代。就目前而言,xrange()
对象确实有__len__
方法,并且元组和列表使用的_PyObject_LengthHint()
function used将利用此方法设置正确的目标大小一次。因此,在这种情况下,list()
代码只是巧妙地提高效率,因为它内联迭代以避免NULL
比较。
跟我来说明代码;在这种情况下唯一真正的区别是迭代器如何展开并且值被复制。由于list()
和tuple()
对象跟踪不同的信息,因此这些循环在实现中略有不同。参见:
PySequence_Tuple()
用于tuple()
listextend()
用于list()
tuple()
代码路径使用PyIter_Next()
,而list()
代码路径则表示不必对NULL
进行两次测试。除此之外,循环执行相同的工作量。我认为这是NULL
测试,放大超过60万次迭代,考虑到这里的时差。
无论如何,你发现的时差确实不大;在我的机器上重复运行将时间差保持在10%以内(每次list
获胜)。时差随着使用的xrange()
的大小线性增加。
答案 1 :(得分:1)
我猜这很大程度上取决于你的运行时间。例如。在cpython中,list和tuple函数都用C编码,并且由于列表的使用非常频繁,因此列表方法很可能比元组方法看到更多的优化。
其他实现可能表现不同。