为什么Python3中没有xrange函数? [英] Why is there no xrange function in Python3?

查看:224
本文介绍了为什么Python3中没有xrange函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Recently I started using Python3 and it's lack of xrange hurts.

简单的例子:

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

1) 1.53888392448 2) 3.215819835662842

那是为什么?我的意思是,为什么xrange被删除了?这是一个很棒的学习工具.对于初学者来说,就像我自己一样,就像我们所有人都处在某个时刻一样.为什么要删除它?有人可以指出我正确的PEP吗?

Why is that? I mean, why xrange's been removed? It's such a great tool to learn. For the beginners, just like myself, like we all were at some point. Why remove it? Can somebody point me to the proper PEP, I can't find it.

干杯.

推荐答案

使用timeit而不是尝试使用time手动进行某些性能测量.

Some performance measurements, using timeit instead of trying to do it manually with time.

首先,Apple 2.7.2 64位:

First, Apple 2.7.2 64-bit:

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位:

Now, python.org 3.3.0 64-bit:

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.x range确实比2.x xrange慢一点. OP的xrange功能与此无关. (不足为奇,因为一次__iter__插槽的一次调用不太可能在循环中发生的1000万次调用中看到,但有人提出来了).

Apparently, 3.x range really is a bit slower than 2.x xrange. And the OP's xrange function has nothing to do with it. (Not surprising, as a one-time call to the __iter__ slot isn't likely to be visible among 10000000 calls to whatever happens in the loop, but someone brought it up as a possibility.)

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

But it's only 30% slower. How did the OP get 2x as slow? Well, if I repeat the same tests with 32-bit Python, I get 1.58 vs. 3.12. So my guess is that this is yet another of those cases where 3.x has been optimized for 64-bit performance in ways that hurt 32-bit.

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

But does it really matter? Check this out, with 3.3.0 64-bit again:

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

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

So, building the list takes more than twice as long than the entire iteration.

在我的测试中,比Python 2.6+消耗的资源要多得多",看起来3.x range的大小与2.x xrange的大小完全相同,即使的大小是原来的10倍,那么构建不必要的列表仍然比范围迭代可能做的任何事情多出10000000倍.

And as for "consumes much more resources than Python 2.6+", from my tests, it looks like a 3.x range is exactly the same size as a 2.x xrange—and, even if it were 10x as big, building the unnecessary list is still about 10000000x more of a problem than anything the range iteration could possibly do.

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

And what about an explicit for loop instead of the C loop inside 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的实际工作中所浪费的时间一样.

So, almost as much time wasted in the for statement as in the actual work of iterating the range.

如果您担心优化范围对象的迭代,则可能在错误的位置.

If you're worried about optimizing the iteration of a range object, you're probably looking in the wrong place.

同时,您一直在问为什么删除xrange,无论人们告诉您多少次相同的事情,但是我会再次重复:它没有被删除:它被重命名为range,并且2.x range是已删除的内容.

Meanwhile, you keep asking why xrange was removed, no matter how many times people tell you the same thing, but I'll repeat it again: It was not removed: it was renamed to range, and the 2.x range is what was removed.

这里有一些证据表明3.3 range对象是2.x xrange对象(而不是2.x range函数)的直接后代:更改历史记录(我相信链接到,该更改将替换文件中任何位置的字符串"xrange"的最后一个实例).

Here's some proof that the 3.3 range object is a direct descendant of the 2.x xrange object (and not of the 2.x range function): the source to 3.3 range and 2.7 xrange. You can even see the change history (linked to, I believe, the change that replaced the last instance of the string "xrange" anywhere in the file).

那么,为什么它变慢?

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

Well, for one, they've added a lot of new features. For another, they've done all kinds of changes all over the place (especially inside iteration) that have minor side effects. And there'd been a lot of work to dramatically optimize various important cases, even if it sometimes slightly pessimizes less important cases. Add this all up, and I'm not surprised that iterating a range as fast as possible is now a bit slower. It's one of those less-important cases that nobody would ever care enough to focus on. No one is likely to ever have a real-life use case where this performance difference is the hotspot in their code.

这篇关于为什么Python3中没有xrange函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆