列表索引效率(python 2与python 3)

列表索引效率(python 2与python 3),python,performance,indexing,osx-leopard,Python,Performance,Indexing,Osx Leopard,在回答另一个问题时,我建议使用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) 我使用pyt

在回答另一个问题时,我建议使用
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)--英特尔Core2Duo

对我来说,这似乎是一个非常显著的差异(超过1.5个差异的因素)。有没有人知道为什么python3会慢得多——特别是对于这样一个普通的操作

编辑

我在我的UbuntuLinux桌面(英特尔i7)上运行了相同的代码,并获得了与python2.6和Python3.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
以及:

更新

我刚刚从安装了python2.7.3和python3.2.3的新版本

在这两种情况下,我都采取了

“Python x.x.3 Mac OS x 32位i386/PPC安装程序(适用于Mac OS x 10.3至10.6[2])”

因为我使用的是OSX10.5。以下是新的时间安排(通过多次试验合理地保持一致):

python 2.7

$python2.7 test.py
0.577006101608
0.590042829514
python 3.2.3

$python3.2 test.py
0.8882801532745361
1.034242868423462

这似乎是Python3.2某些版本的产物。目前最好的假设是,所有32位Intel版本都会减速,但没有64位版本会减速。请继续阅读以了解更多详细信息

您没有运行足够的测试来确定任何内容。重复你的测试很多次,我得到的值在0.31到0.54之间,这是一个巨大的变化

因此,我使用一系列不同的Python2和Python3安装,使用数字
10x
repeat=10
运行了您的测试。抛开顶部和底部的结果,取其他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
因此,看起来3.2在
[99]
中的速度实际上稍微快一点,在
[-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 vs.gcc 4.2或clang、硬件差异等。它有助于在Leopard下测试64位构建,使用不同的编译器等,但不幸的是,我的Leopard box是第一代Intel Mini(具有32位核心的单CPU),所以我无法进行测试

作为进一步的间接证据,我在Lion box上运行了一系列其他快速测试,看起来32位3.2比2.x慢50%,而64位3.2可能比2.x快一点。但如果我们真的想支持这一点,就需要有人挑选并运行一个真正的基准测试套件

无论如何,我在这一点上的最佳猜测是,在优化3.x分支时,没有人在32位i386 Mac构建上投入太多精力。这实际上是他们做出的合理选择

或者,他们甚至没有在32位i386周期上投入太多精力。这种可能性可能解释了为什么OP saw 2.x和3.2在linux机器上给出了类似的结果,而Otto Allmendinger在linux机器上看到3.2比2.6慢。但由于他们都没有提到是运行32位还是64位linux,所以很难知道这是否相关


我们还没有排除许多其他不同的可能性,但这似乎是最好的一个。

下面的代码至少说明了部分答案:

$ 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类型。

python3
range()
是Python2
xrange()
。如果要在Python3代码中模拟Python2
range()
,必须使用
list(range(num)
。num越大,与原始代码的差异就越大


索引应该独立于列表中存储的内容,因为列表只存储对目标对象的引用。引用是非类型化的,并且都是相同的类型。因此,从技术上讲,列表类型是一种同构的数据结构。索引意味着将索引值转换为起始地址+偏移量。计算偏移量i最多一次减法非常有效。与其他操作相比,这是非常便宜的额外操作。

尝试使用
xrange()
在python 2中。x@AshwiniChaudhary--这些东西都在
设置中
,没有计时。
xrange
vs
range
应该与之无关。仅供参考:有答案讨论了python3.0中缺少小整数的特殊大小写,也许python3中仍然缺少它。2@OttoAllmendinger这与其中的一些答案一致(OS-X与Linux的区别要大得多)。你可能是对的。@mgilson我的结果与你在我的Linux机器上的结果大致一致。OS-X 10.5.8是一个32位操作系统,因此如果我愿意,我无法运行64位版本。Leopard可以运行64位应用程序。与Snow Leopard不同,至少在Intel上,它只有32位内核,而且大多数内置应用程序都是32位的nd股票gcc默认为32位,但它仍然可以构建和运行64位应用程序虽然我不是100%相信这就是原因。我已经发布了我的两台机器的启动横幅和处理器。据我所知,看起来我从同一个地方安装了两个python,使用同一个编译器编译。如果其他人可以使用OS-X 10.5.8复制您的测试,我可能会相信。(如果没有其他问题,我可能会接受这个答案--
$ 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