最近我开始使用Python3,它没有xrange次受伤.

简单示例:

  1. Python 2:

    from time import time as t
    def count():
      st = t()
      [x for x in xrange(10000000) if x%4 == 0]
      et = t()
      print et-st
    count()
    
  2. Python 3:

    from time import time as t
    
    def xrange(x):
    
        return iter(range(x))
    
    def count():
        st = t()
        [x for x in xrange(10000000) if x%4 == 0]
        et = t()
        print (et-st)
    count()
    

结果分别是:

  1. 1.53888392448
  2. 3.215819835662842

为什么?我是说,为什么xrange个被移除了?这是一个很好的学习工具.对于初学者来说,就像我一样,就像我们在某个时刻一样.为什么要移除它?谁能给我指一下合适的政治人物,我找不到.

推荐答案

一些性能测量,使用timeit,而不是try 手动使用time.

首先,Apple 2.7.2 64位:

In [37]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.05 s per loop

现在,python.org 3.3.0 64位:

In [83]: %timeit collections.deque((x for x in range(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.32 s per loop

In [84]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0)
1 loops, best of 3: 1.31 s per loop

In [85]: %timeit collections.deque((x for x in iter(range(10000000)) if x%4 == 0), maxlen=0) 
1 loops, best of 3: 1.33 s per loop

显然是3.Xrange确实比2慢一点.xxrange.OP的xrange函数与此无关.(这并不奇怪,因为对__iter__插槽的一次性调用不太可能在对循环中发生的任何事情的range00000次调用中可见,但有人提出了这种可能性.)

但它只慢了30%.行动怎么会慢2倍呢?如果我用32位Python重复相同的测试,我会得到1.58对3.12.所以我的猜测是,这是3.x以损害32位的方式针对64位性能进行优化的又一种情况.

但这真的重要吗?看看这个,再次使用3.3.0 64位:

In [86]: %timeit [x for x in range(10000000) if x%4 == 0]
1 loops, best of 3: 3.65 s per loop

因此,构建list所需的时间是整个迭代的两倍多.

至于"比Python2.6+消耗更多的资源",从我的测试来看,它看起来像一个3.Xrange的尺寸和2的尺寸完全一样.xxrange,而且,即使它是10倍大,构建不必要的列表仍然是一个比范围迭代可能做的任何事情都多出大约range0000000倍的问题.

那么用显式for循环代替deque中的C循环呢?

In [87]: def consume(x):
   ....:     for i in x:
   ....:         pass
In [88]: %timeit consume(x for x in range(10000000) if x%4 == 0)
1 loops, best of 3: 1.85 s per loop

因此,在for语句中浪费的时间几乎与在迭代range语句的实际工作中浪费的时间一样多.

如果你担心优化范围对象的迭代,你可能找错了地方.


与此同时,你一直在问为什么xrange被移除了,不管人们多少次告诉你同样的事情,但我再重复一遍:它没有被移除:它被重新命名为range,2.x range就是被移除的.

这里有一些证据证明3.3 range对象是2的直系后代.xxrange对象(而不是2.xrange函数):3.3 range2.7 xrange的源.您甚至可以看到change history(我相信,它链接到了替换文件中任意位置字符串"xrange"的最后一个实例的更改).

那么,为什么要慢一点呢?

首先,他们增加了很多新功能.另一方面,他们在各地做了各种各样的改变(尤其是在迭代过程中),这些改变的副作用很小.而且已经有很多工作在戏剧性地优化各种重要 case ,即使有时它会稍微悲观一些不太重要的 case .把这些加起来,我并不惊讶尽可能快地迭代range现在会慢一点.这是那些不太重要的案件之一,没有人会足够关注.在现实生活中,没有人可能会遇到这样的用例:这种性能差异是他们代码中的热点.

Python相关问答推荐

Python中的函数中是否有充分的理由接受float而不接受int?

具有多个选项的计数_匹配

使用SciPy进行曲线匹配未能给出正确的匹配

时间序列分解

试图找到Python方法来部分填充numpy数组

根据在同一数据框中的查找向数据框添加值

Python上的Instagram API:缺少client_id参数"

查找两极rame中组之间的所有差异

为什么符号没有按顺序添加?

Python库:可选地支持numpy类型,而不依赖于numpy

numpy卷积与有效

如何在Raspberry Pi上检测USB并使用Python访问它?

计算分布的标准差

如何使regex代码只适用于空的目标单元格

从列表中获取n个元素,其中list [i][0]== value''

提高算法效率的策略?

Js的查询结果可以在PC Chrome上显示,但不能在Android Chrome、OPERA和EDGE上显示,而两者都可以在Firefox上运行

解决Geopandas和Altair中的正图和投影问题

Matplotlib中的曲线箭头样式

在一个数据帧中,我如何才能发现每个行号是否出现在一列列表中?