当前位置: 首页 > 面试题库 >

为什么Python3中没有xrange函数?

甄越
2023-03-14
问题内容

最近,我开始使用Python3,它缺乏xrange的好处。

简单的例子:

1) Python2:

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) Python3:

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被删除了?这是学习的好工具。对于初学者来说,就像我自己一样,就像我们都处在某个时刻。为什么要删除它?有人可以指出我正确的PEP,我找不到它。

干杯。


问题答案:

进行一些性能评估,timeit而不是尝试使用手动进行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.x慢一些xrange。OP的xrange功能与此无关。(不足为奇,因为__iter__循环中发生的任何事情的1000万次调用中,对插槽的一次性调用不太可能看到,但有人提出来了。)

但这仅慢了30%。OP如何使速度慢2倍?好吧,如果我对32位Python重复相同的测试,则得出的结果是1.58和3.12。因此,我的猜测是,这是3.x针对64位性能进行了优化(以损害32位的方式)的又一案例。

但这真的重要吗?再次使用64位3.3.0进行检查:

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

因此,构建所需的list时间是整个迭代的两倍以上。

至于“比Python
2.6+消耗更多的资源”,在我的测试中,看起来3.xrange的大小与2.x的大小完全相同xrange,即使它的大小是10x的大小,也可以构建不必要的列表问题仍然比范围迭代可能做的任何事情多出10000000x。

那么显式for循环而不是内部的C循环deque呢?

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.xrange是被删除的。

这是3.3range对象是2.xxrange对象(而不是2.xrange函数)的直接后代的证明:3.3range和2.7xrange的源。您甚至可以查看更改历史记录(我相信,该更改已链接到替换文件中任何位置的字符串“
xrange”的最后一个实例的更改)。

那么,为什么它变慢?

好吧,其中之一是,他们添加了许多新功能。另一方面,他们已经在整个地方(尤其是在迭代过程中)进行了各种具有较小副作用的更改。尽管有时有时会稍微低估不太重要的案例,但仍进行了大量工作来显着优化各种重要案例。将所有这些加起来,range对于尽快进行迭代现在变得慢一点,我并不感到惊讶。这是最重要的案例之一,没有人会足够关注。没有人会遇到现实生活中的用例,这种性能差异是他们代码中的热点。



 类似资料:
  • 我正在学习Java,正在使用java 8,spring 5.3.9和Apache Tomcat 9。我已经将我的jar文件添加到我的构建路径中的类路径中,将Apache Tomcat添加到我的服务器中,我的项目运行得非常好。现在我开始使用beans和xml文件,我遇到了一个问题。我的代码的一部分被触发,另一部分被忽略。 我有以下界面 FortuneService.java: 和一个快乐财富服务类:

  • 问题内容: 显然xrange更快,但我不知道为什么它更快(到目前为止,除了轶事之外还没有证据表明它更快)或除此之外还有什么不同 问题答案: 在Python 2.x中: 创建一个列表,所以如果你这样做,则会在内存中创建一个包含9999999元素的列表。 是一个延迟计算的序列对象。 在Python 3中,它等效于,并且必须使用来获取列表。

  • 问题内容: 有没有理由 但不是 ? 如何正确过滤列表?我可以用 当然可以,但是如果我理解正确的话,就不能保证我的订购顺序保持不变。 问题答案: 它之所以未实现,是因为它会在返回的List视图上暴露大量危险的慢速方法,例如#get(index)(会引发性能错误)。ListIterator也很难实现(尽管我几年前提交了一个补丁来解决)。 由于索引方法在过滤后的列表视图中效率不高,因此最好使用不包含它们

  • < b >想改进这个问题?更新问题,以便通过编辑此帖子用事实和引用来回答问题。 为什么没有函数(没有任何参数)来展平

  • 问题内容: Java为什么不支持C ++中的复制构造函数? 问题答案: Java。只是没有像在C ++中那样隐式地调用它们,我怀疑这是您的真正问题。 首先,复制构造函数无非是: 现在,C ++将使用以下语句隐式调用复制构造函数: 在这种情况下,克隆/复制在Java中根本没有意义,因为所有b1和b2都是引用,而不是像C 中那样的值对象。在C 中,该语句复制对象的状态。在Java中,它只是复制 引用

  • 问题内容: 我知道每次键入字符串文字时,字符串池中都会引用相同的String对象。 但是,为什么String API不包含,所以我可以使用引用? 至少,这将节省编译时间,因为编译器将知道引用现有的String,而不必检查是否已创建它以进行重用,对吗?我个人认为,字符串文字(尤其是很小的文字)在许多情况下是一种“代码异味”。 那么是否没有String.Empty背后的宏伟设计原因,还是语言创建者根本