在回答另一个question时,我建议使用timeit
来测试使用正整数和负整数索引列表之间的区别。这是代码:
import timeit
t=timeit.timeit('mylist[99]',setup='mylist=list(range(100))',number=10000000)
print (t)
t=timeit.timeit('mylist[-1]',setup='mylist=list(range(100))',number=10000000)
print (t)
我使用python 2.6运行此代码:
$ python2.6 test.py
0.587687015533
0.586369991302
然后我用python 3.2运行它:
$ python3.2 test.py
0.9212150573730469
1.0225799083709717
然后我挠了挠头,做了一些谷歌搜索,并决定在这里发布这些观察结果。
操作系统:OS-X(10.5.8) - Intel Core2Duo
这对我来说似乎是一个非常显着的差异(差异超过1.5)。有没有人知道为什么python3这么慢 - 特别是对于这样一个常见的操作?
修改
我在我的Ubuntu Linux桌面(Intel i7)上运行相同的代码,并使用python2.6和python 3.2获得了可比较的结果。似乎这是一个依赖于操作系统(或处理器)的问题(其他用户在Linux机器上看到相同的行为 - 请参阅注释)。
编辑2
在其中一个答案中请求了启动横幅,所以这里是:
Python 2.6.4 (r264:75821M, Oct 27 2009, 19:48:32)
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
和
Python 3.2 (r32:88452, Feb 20 2011, 10:19:59)
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
更新
我刚从http://www.python.org/download/
安装了新版本的python2.7.3和python3.2.3在这两种情况下,我都拿了
“Python x.x.3 Mac OS X 32位i386 / PPC安装程序(适用于Mac OS X 10.3到10.6 [2])”
因为我在OS X 10.5上。以下是新时间(通过多次试验合理一致):
python 2.7
$python2.7 test.py
0.577006101608
0.590042829514
python 3.2.3
$python3.2 test.py
0.8882801532745361
1.034242868423462
答案 0 :(得分:24)
这似乎是Python 3.2的一些版本的工件。在这一点上,最好的假设是所有32位英特尔版本都有减速,但没有64位版本。继续阅读以获取更多详细信息。
你没有运行足够的测试来确定任何事情。多次重复测试,我在同一测试中得到的值介于0.31到0.54之间,这是一个巨大的变化。
因此,我使用10x
数字和repeat=10
使用一堆不同的Python2和Python3安装来运行测试。丢掉顶部和底部的结果,平均其他8,然后除以10(得到一个相当于你的测试的数字),这就是我所看到的:
1. 0.52/0.53 Lion 2.6
2. 0.49/0.50 Lion 2.7
3. 0.48/0.48 MacPorts 2.7
4. 0.39/0.49 MacPorts 3.2
5. 0.39/0.48 HomeBrew 3.2
因此,使用[99]
看起来3.2实际上稍快一点,与[-1]
的速度大致相同。
然而,在10.5机器上,我得到了这些结果:
1. 0.98/1.02 MacPorts 2.6
2. 1.47/1.59 MacPorts 3.2
回到原始(Lion)机器上,我以32位模式运行,并得到了这个:
1. 0.50/0.48 Homebrew 2.7
2. 0.75/0.82 Homebrew 3.2
所以,似乎32位是重要的,而不是Leopard vs. Lion,gcc 4.0与gcc 4.2或clang,硬件差异等等。它将有助于测试Leopard下的64位版本,具有不同的编译器等,但不幸的是我的Leopard盒子是第一代Intel Mini(带有32位Core Solo CPU),所以我不能做那个测试。
作为进一步的间接证据,我在Lion盒子上运行了大量其他快速测试,看起来32位3.2比2.x慢约50%,而64位3.2可能更快一点比2.x.但是如果我们真的想要支持那个,那么有人需要选择并运行一个真正的基准测试套件。
无论如何,我最好的猜测是,在优化3.x分支时,没有人在32位i386 Mac版本上投入太多精力。这对他们来说实际上是一个合理的选择。
或者,或者,他们甚至没有在32位i386期间投入太多精力。这种可能性可以解释为什么OP看到2.x和3.2在linux盒子上给出类似的结果,而Otto Allmendinger看到3.2在linux盒子上同样慢到2.6。但由于他们都没有提到他们是在运行32位还是64位Linux,因此很难知道这是否相关。还有很多其他不同的可能性我们还没有排除,但这似乎是最好的。
答案 1 :(得分:4)
这是一个代码,至少说明了答案的一部分:
$ python
Python 2.7.3 (default, Apr 20 2012, 22:44:07)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import timeit
>>> t=timeit.timeit('mylist[99]',setup='mylist=list(range(100))',number=50000000)
>>> print (t)
2.55517697334
>>> t=timeit.timeit('mylist[99L]',setup='mylist=list(range(100))',number=50000000)
>>> print (t)
3.89904499054
$ python3
Python 3.2.3 (default, May 3 2012, 15:54:42)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import timeit
>>> t=timeit.timeit('mylist[99]',setup='mylist=list(range(100))',number=50000000)
>>> print (t)
3.9906489849090576
python3没有旧的int类型。
答案 2 :(得分:0)
Python 3 range()
是Python 2 xrange()
。如果要在Python 3代码中模拟Python 2 range()
,则必须使用list(range(num)
。 num
越大,您的原始代码就会出现更大的差异。
索引应独立于列表中存储的内容,因为列表仅存储对目标对象的引用。引用是无类型的,都是相同类型的。因此,列表类型是一种同类数据结构 - 从技术上讲。索引意味着将索引值转换为起始地址+偏移量。计算偏移量非常有效,最多一次减法。与其他操作相比,这是非常便宜的额外操作。