标签归档:xrange

为什么Python3中没有xrange函数?

问题:为什么Python3中没有xrange函数?

最近,我开始使用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,我找不到它。

干杯。

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

Simple example:

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()

The results are, respectively:

1) 1.53888392448 2) 3.215819835662842

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.

Cheers.


回答 0

进行一些性能评估,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.x range确实比2.x慢一些xrange。OP的xrange功能与此无关。(不足为奇,因为__iter__在循环中发生的任何事情的1000 万次调用中,对插槽的一次性调用不太可能可见,但有人提出来了。)

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

但这真的重要吗?再次使用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时间是整个迭代的两倍以上。

至于“比Python 2.6+消耗更多的资源”,在我的测试中,看起来3.x range的大小与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.x range是被删除的东西。

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

那么,为什么它变慢?

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

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

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

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

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.)

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.

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

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

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.

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

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.


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.

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).

So, why is it slower?

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.


回答 1

Python3的范围 Python2的xrange。无需在其周围包装迭代器。要获得Python3中的实际列表,您需要使用list(range(...))

如果您想要适用于Python2和Python3的产品,请尝试以下操作

try:
    xrange
except NameError:
    xrange = range

Python3’s range is Python2’s xrange. There’s no need to wrap an iter around it. To get an actual list in Python3, you need to use list(range(...))

If you want something that works with Python2 and Python3, try this

try:
    xrange
except NameError:
    xrange = range

回答 2

Python 3的range类型与Python 2的类型一样xrange。我不确定为什么会看到速度变慢,因为函数直接返回的迭代器xrange正是您返回的迭代器range

我无法在系统上重现速度下降的情况。这是我的测试方式:

Python 2,具有xrange

Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)
18.631936646865853

Python 3,range速度稍微快一点:

Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)
17.31399508687869

我最近了解到Python 3的range类型还具有其他一些简洁的功能,例如对切片的支持:range(10,100,2)[5:25:5]is range(20, 60, 10)

Python 3’s range type works just like Python 2’s xrange. I’m not sure why you’re seeing a slowdown, since the iterator returned by your xrange function is exactly what you’d get if you iterated over range directly.

I’m not able to reproduce the slowdown on my system. Here’s how I tested:

Python 2, with xrange:

Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)
18.631936646865853

Python 3, with range is a tiny bit faster:

Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)
17.31399508687869

I recently learned that Python 3’s range type has some other neat features, such as support for slicing: range(10,100,2)[5:25:5] is range(20, 60, 10)!


回答 3

修复python2代码的一种方法是:

import sys

if sys.version_info >= (3, 0):
    def xrange(*args, **kwargs):
        return iter(range(*args, **kwargs))

One way to fix up your python2 code is:

import sys

if sys.version_info >= (3, 0):
    def xrange(*args, **kwargs):
        return iter(range(*args, **kwargs))

回答 4

Python 2中的xrange是一个生成器,它实现了迭代器,而range只是一个函数。在Python3中,我不知道为什么将其从xrange中删除。

xrange from Python 2 is a generator and implements iterator while range is just a function. In Python3 I don’t know why was dropped off the xrange.


回答 5

comp:〜$ python Python 2.7.6(默认,2015年6月22日,17:58:13)[gcc 4.8.2]在linux2上

>>> import timeit
>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)

5.656799077987671

>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)

5.579368829727173

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

21.54827117919922

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

22.014557123184204

当timeit number = 1参数时:

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=1)

0.2245171070098877

>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=1)

0.10750913619995117

comp:〜$ python3 Python 3.4.3(默认,2015年10月14日,20:28:29)[GCC 4.8.4]在Linux上

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

9.113872020003328

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

9.07014398300089

timeit number = 1,2,3,4参数可以快速且线性地工作:

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=1)

0.09329321900440846

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=2)

0.18501482300052885

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=3)

0.2703447980020428

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=4)

0.36209142999723554

因此,看来如果我们测量1个运行循环周期,例如timeit.timeit(“ [x表示x在range(1000000)中,如果x%4]”,number = 1)(正如我们在实际代码中实际使用的那样),python3的运行速度足够快,但在重复循环中,python 2 xrange()在速度上胜过python 3中的range()。

comp:~$ python Python 2.7.6 (default, Jun 22 2015, 17:58:13) [GCC 4.8.2] on linux2

>>> import timeit
>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)

5.656799077987671

>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)

5.579368829727173

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

21.54827117919922

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

22.014557123184204

With timeit number=1 param:

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=1)

0.2245171070098877

>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=1)

0.10750913619995117

comp:~$ python3 Python 3.4.3 (default, Oct 14 2015, 20:28:29) [GCC 4.8.4] on linux

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

9.113872020003328

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

9.07014398300089

With timeit number=1,2,3,4 param works quick and in linear way:

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=1)

0.09329321900440846

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=2)

0.18501482300052885

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=3)

0.2703447980020428

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=4)

0.36209142999723554

So it seems if we measure 1 running loop cycle like timeit.timeit(“[x for x in range(1000000) if x%4]”,number=1) (as we actually use in real code) python3 works quick enough, but in repeated loops python 2 xrange() wins in speed against range() from python 3.


NameError:全局名称“ xrange”未在Python 3中定义

问题:NameError:全局名称“ xrange”未在Python 3中定义

运行python程序时出现错误:

Traceback (most recent call last):
  File "C:\Program Files (x86)\Wing IDE 101 4.1\src\debug\tserver\_sandbox.py", line 110, in <module>
  File "C:\Program Files (x86)\Wing IDE 101 4.1\src\debug\tserver\_sandbox.py", line 27, in __init__
  File "C:\Program Files (x86)\Wing IDE 101 4.1\src\debug\tserver\class\inventory.py", line 17, in __init__
builtins.NameError: global name 'xrange' is not defined

游戏是从这里开始的

是什么导致此错误?

I am getting an error when running a python program:

Traceback (most recent call last):
  File "C:\Program Files (x86)\Wing IDE 101 4.1\src\debug\tserver\_sandbox.py", line 110, in <module>
  File "C:\Program Files (x86)\Wing IDE 101 4.1\src\debug\tserver\_sandbox.py", line 27, in __init__
  File "C:\Program Files (x86)\Wing IDE 101 4.1\src\debug\tserver\class\inventory.py", line 17, in __init__
builtins.NameError: global name 'xrange' is not defined

The game is from here.

What causes this error?


回答 0

您正在尝试使用Python 3运行Python 2代码库。在Python 3中xrange()已重命名为range()

而是使用Python 2运行游戏。不要试图将它移植,除非你知道自己在做什么,很可能会出现超越更多的问题xrange()range()

作为记录,您看到的不是语法错误,而是运行时异常。


如果您确实知道自己在做什么,并且正在积极地使Python 2代码库与Python 3兼容,则可以通过将全局名称添加为模块的别名来桥接代码range。(请注意,您可能必须更新range()Python 2代码库中的所有现有用法,list(range(...))以确保仍然在Python 3中获得列表对象):

try:
    # Python 2
    xrange
except NameError:
    # Python 3, xrange is now named range
    xrange = range

# Python 2 code that uses xrange(...) unchanged, and any
# range(...) replaced with list(range(...))

或更换的所有用途xrange(...)range(...)在代码库,然后使用不同的垫片,使与Python 2的Python语法3兼容:

try:
    # Python 2 forward compatibility
    range = xrange
except NameError:
    pass

# Python 2 code transformed from range(...) -> list(range(...)) and
# xrange(...) -> range(...).

对于希望长期与Python 3兼容的代码库而言,后者是更可取的,因此只要有可能,便更容易使用Python 3语法。

You are trying to run a Python 2 codebase with Python 3. xrange() was renamed to range() in Python 3.

Run the game with Python 2 instead. Don’t try to port it unless you know what you are doing, most likely there will be more problems beyond xrange() vs. range().

For the record, what you are seeing is not a syntax error but a runtime exception instead.


If you do know what your are doing and are actively making a Python 2 codebase compatible with Python 3, you can bridge the code by adding the global name to your module as an alias for range. (Take into account that you may have to update any existing range() use in the Python 2 codebase with list(range(...)) to ensure you still get a list object in Python 3):

try:
    # Python 2
    xrange
except NameError:
    # Python 3, xrange is now named range
    xrange = range

# Python 2 code that uses xrange(...) unchanged, and any
# range(...) replaced with list(range(...))

or replace all uses of xrange(...) with range(...) in the codebase and then use a different shim to make the Python 3 syntax compatible with Python 2:

try:
    # Python 2 forward compatibility
    range = xrange
except NameError:
    pass

# Python 2 code transformed from range(...) -> list(range(...)) and
# xrange(...) -> range(...).

The latter is preferable for codebases that want to aim to be Python 3 compatible only in the long run, it is easier to then just use Python 3 syntax whenever possible.


回答 1

添加xrange=range您的代码:)对我有用。

add xrange=range in your code :) It works to me.


回答 2

我加入这个解决进口问题的
更多信息

from past.builtins import xrange

I solved the issue by adding this import
More info

from past.builtins import xrange

回答 3

在python 2.x中,xrange用于返回生成器,而range用于返回列表。在python 3.x中,xrange已被删除,并且range返回一个生成器,就像python 2.x中的xrange一样。因此,在python 3.x中,您需要使用range而不是xrange。

in python 2.x, xrange is used to return a generator while range is used to return a list. In python 3.x , xrange has been removed and range returns a generator just like xrange in python 2.x. Therefore, in python 3.x you need to use range rather than xrange.


回答 4

更换

Python 2 xrange

Python 3 range

休息都一样。

Replace

Python 2 xrange to

Python 3 range

Rest all same.


回答 5

我同意最后一个答案。但是还有另一种方法可以解决此问题。您可以下载名为future的软件包,例如pip install future。然后在.py文件中输入“ from past.builtins import xrange”。此方法用于文件中有很多xrange的情况。

I agree with the last answer.But there is another way to solve this problem.You can download the package named future,such as pip install future.And in your .py file input this “from past.builtins import xrange”.This method is for the situation that there are many xranges in your file.


您是否应该始终偏爱xrange()而不是range()?

问题:您是否应该始终偏爱xrange()而不是range()?

为什么或者为什么不?

Why or why not?


回答 0

对于性能,尤其是在较大范围内进行迭代时,xrange()通常会更好。但是,在某些情况下,您可能更喜欢range()

  • 在python 3中,做过range()什么xrange()事并且xrange()不存在。如果要编写可在Python 2和Python 3上运行的代码,则不能使用xrange()

  • range()在某些情况下实际上可以更快-例如。如果多次重复相同的序列。 xrange()每次都必须重新构造整数对象,但是range()将拥有真正的整数对象。(但是,在内存方面,它总是会表现得更差)

  • xrange()在需要真实列表的所有情况下都不可用。例如,它不支持切片或任何列表方法。

[编辑]有range()几篇文章提到2to3工具将如何升级。为了记录在案,这里是对一些用法示例运行该工具的输出range()xrange()

RefactoringTool: Skipping implicit fixer: buffer
RefactoringTool: Skipping implicit fixer: idioms
RefactoringTool: Skipping implicit fixer: ws_comma
--- range_test.py (original)
+++ range_test.py (refactored)
@@ -1,7 +1,7 @@

 for x in range(20):
-    a=range(20)
+    a=list(range(20))
     b=list(range(20))
     c=[x for x in range(20)]
     d=(x for x in range(20))
-    e=xrange(20)
+    e=range(20)

如您所见,当在for循环或理解中使用时,或已经用list()包装的地方,范围保持不变。

For performance, especially when you’re iterating over a large range, xrange() is usually better. However, there are still a few cases why you might prefer range():

  • In python 3, range() does what xrange() used to do and xrange() does not exist. If you want to write code that will run on both Python 2 and Python 3, you can’t use xrange().

  • range() can actually be faster in some cases – eg. if iterating over the same sequence multiple times. xrange() has to reconstruct the integer object every time, but range() will have real integer objects. (It will always perform worse in terms of memory however)

  • xrange() isn’t usable in all cases where a real list is needed. For instance, it doesn’t support slices, or any list methods.

[Edit] There are a couple of posts mentioning how range() will be upgraded by the 2to3 tool. For the record, here’s the output of running the tool on some sample usages of range() and xrange()

RefactoringTool: Skipping implicit fixer: buffer
RefactoringTool: Skipping implicit fixer: idioms
RefactoringTool: Skipping implicit fixer: ws_comma
--- range_test.py (original)
+++ range_test.py (refactored)
@@ -1,7 +1,7 @@

 for x in range(20):
-    a=range(20)
+    a=list(range(20))
     b=list(range(20))
     c=[x for x in range(20)]
     d=(x for x in range(20))
-    e=xrange(20)
+    e=range(20)

As you can see, when used in a for loop or comprehension, or where already wrapped with list(), range is left unchanged.


回答 1

不,它们都有各自的用途:

xrange()在迭代时使用,因为它可以节省内存。说:

for x in xrange(1, one_zillion):

而不是:

for x in range(1, one_zillion):

另一方面,range()如果您确实想要数字列表,请使用。

multiples_of_seven = range(7,100,7)
print "Multiples of seven < 100: ", multiples_of_seven

No, they both have their uses:

Use xrange() when iterating, as it saves memory. Say:

for x in xrange(1, one_zillion):

rather than:

for x in range(1, one_zillion):

On the other hand, use range() if you actually want a list of numbers.

multiples_of_seven = range(7,100,7)
print "Multiples of seven < 100: ", multiples_of_seven

回答 2

仅当需要实际列表时range()xrange()才应优先考虑。例如,当您想修改所返回的列表range()时,或者希望对其进行切片时。对于迭代,甚至只是普通索引,xrange()都可以正常工作(通常效率更高)。有一点range()要比xrange()很小的列表快一点,但是取决于您的硬件和其他各种细节,收支平衡可能是长度为1或2的结果;不用担心。更喜欢xrange()

You should favour range() over xrange() only when you need an actual list. For instance, when you want to modify the list returned by range(), or when you wish to slice it. For iteration or even just normal indexing, xrange() will work fine (and usually much more efficiently). There is a point where range() is a bit faster than xrange() for very small lists, but depending on your hardware and various other details, the break-even can be at a result of length 1 or 2; not something to worry about. Prefer xrange().


回答 3

另一个区别是xrange()不能支持大于C ints的数字,因此,如果要使用python内置的支持大数的数字来获得范围,则必须使用range()。

Python 2.7.3 (default, Jul 13 2012, 22:29:01) 
[GCC 4.7.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> range(123456787676676767676676,123456787676676767676679)
[123456787676676767676676L, 123456787676676767676677L, 123456787676676767676678L]
>>> xrange(123456787676676767676676,123456787676676767676679)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: Python int too large to convert to C long

Python 3没有这个问题:

Python 3.2.3 (default, Jul 14 2012, 01:01:48) 
[GCC 4.7.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> range(123456787676676767676676,123456787676676767676679)
range(123456787676676767676676, 123456787676676767676679)

One other difference is that xrange() can’t support numbers bigger than C ints, so if you want to have a range using python’s built in large number support, you have to use range().

Python 2.7.3 (default, Jul 13 2012, 22:29:01) 
[GCC 4.7.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> range(123456787676676767676676,123456787676676767676679)
[123456787676676767676676L, 123456787676676767676677L, 123456787676676767676678L]
>>> xrange(123456787676676767676676,123456787676676767676679)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: Python int too large to convert to C long

Python 3 does not have this problem:

Python 3.2.3 (default, Jul 14 2012, 01:01:48) 
[GCC 4.7.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> range(123456787676676767676676,123456787676676767676679)
range(123456787676676767676676, 123456787676676767676679)

回答 4

xrange()效率更高,因为它无需生成对象列表,而只是一次生成一个对象。一次只能有一个整数,而不是100个整数及其所有开销和放入它们的列表。生成速度更快,内存使用更好,代码更高效。

除非我特别需要某件事的清单,否则我总是会支持 xrange()

xrange() is more efficient because instead of generating a list of objects, it just generates one object at a time. Instead of 100 integers, and all of their overhead, and the list to put them in, you just have one integer at a time. Faster generation, better memory use, more efficient code.

Unless I specifically need a list for something, I always favor xrange()


回答 5

range()返回一个列表,xrange()返回一个xrange对象。

xrange()更快,内存使用效率更高。但是收益不是很大。

列表使用的额外内存当然不只是浪费,列表还具有更多功能(切片,重复,插入等)。确切的差异可以在文档中找到。没有硬性规定,请使用所需的。

Python 3.0仍在开发中,但是IIRC range()与2.X的xrange()非常相似,并且list(range())可用于生成列表。

range() returns a list, xrange() returns an xrange object.

xrange() is a bit faster, and a bit more memory efficient. But the gain is not very large.

The extra memory used by a list is of course not just wasted, lists have more functionality (slice, repeat, insert, …). Exact differences can be found in the documentation. There is no bonehard rule, use what is needed.

Python 3.0 is still in development, but IIRC range() will very similar to xrange() of 2.X and list(range()) can be used to generate lists.


回答 6

我只想说,获取具有切片和索引功能的xrange对象并不难。我编写了一些代码,这些代码相当有效,并且在计数(迭代)时与xrange一样快。

from __future__ import division

def read_xrange(xrange_object):
    # returns the xrange object's start, stop, and step
    start = xrange_object[0]
    if len(xrange_object) > 1:
       step = xrange_object[1] - xrange_object[0]
    else:
        step = 1
    stop = xrange_object[-1] + step
    return start, stop, step

class Xrange(object):
    ''' creates an xrange-like object that supports slicing and indexing.
    ex: a = Xrange(20)
    a.index(10)
    will work

    Also a[:5]
    will return another Xrange object with the specified attributes

    Also allows for the conversion from an existing xrange object
    '''
    def __init__(self, *inputs):
        # allow inputs of xrange objects
        if len(inputs) == 1:
            test, = inputs
            if type(test) == xrange:
                self.xrange = test
                self.start, self.stop, self.step = read_xrange(test)
                return

        # or create one from start, stop, step
        self.start, self.step = 0, None
        if len(inputs) == 1:
            self.stop, = inputs
        elif len(inputs) == 2:
            self.start, self.stop = inputs
        elif len(inputs) == 3:
            self.start, self.stop, self.step = inputs
        else:
            raise ValueError(inputs)

        self.xrange = xrange(self.start, self.stop, self.step)

    def __iter__(self):
        return iter(self.xrange)

    def __getitem__(self, item):
        if type(item) is int:
            if item < 0:
                item += len(self)

            return self.xrange[item]

        if type(item) is slice:
            # get the indexes, and then convert to the number
            start, stop, step = item.start, item.stop, item.step
            start = start if start != None else 0 # convert start = None to start = 0
            if start < 0:
                start += start
            start = self[start]
            if start < 0: raise IndexError(item)
            step = (self.step if self.step != None else 1) * (step if step != None else 1)
            stop = stop if stop is not None else self.xrange[-1]
            if stop < 0:
                stop += stop

            stop = self[stop]
            stop = stop

            if stop > self.stop:
                raise IndexError
            if start < self.start:
                raise IndexError
            return Xrange(start, stop, step)

    def index(self, value):
        error = ValueError('object.index({0}): {0} not in object'.format(value))
        index = (value - self.start)/self.step
        if index % 1 != 0:
            raise error
        index = int(index)


        try:
            self.xrange[index]
        except (IndexError, TypeError):
            raise error
        return index

    def __len__(self):
        return len(self.xrange)

老实说,我认为整个问题有点傻,无论如何xrange都应该做所有这一切……

I would just like to say that it REALLY isn’t that difficult to get an xrange object with slice and indexing functionality. I have written some code that works pretty dang well and is just as fast as xrange for when it counts (iterations).

from __future__ import division

def read_xrange(xrange_object):
    # returns the xrange object's start, stop, and step
    start = xrange_object[0]
    if len(xrange_object) > 1:
       step = xrange_object[1] - xrange_object[0]
    else:
        step = 1
    stop = xrange_object[-1] + step
    return start, stop, step

class Xrange(object):
    ''' creates an xrange-like object that supports slicing and indexing.
    ex: a = Xrange(20)
    a.index(10)
    will work

    Also a[:5]
    will return another Xrange object with the specified attributes

    Also allows for the conversion from an existing xrange object
    '''
    def __init__(self, *inputs):
        # allow inputs of xrange objects
        if len(inputs) == 1:
            test, = inputs
            if type(test) == xrange:
                self.xrange = test
                self.start, self.stop, self.step = read_xrange(test)
                return

        # or create one from start, stop, step
        self.start, self.step = 0, None
        if len(inputs) == 1:
            self.stop, = inputs
        elif len(inputs) == 2:
            self.start, self.stop = inputs
        elif len(inputs) == 3:
            self.start, self.stop, self.step = inputs
        else:
            raise ValueError(inputs)

        self.xrange = xrange(self.start, self.stop, self.step)

    def __iter__(self):
        return iter(self.xrange)

    def __getitem__(self, item):
        if type(item) is int:
            if item < 0:
                item += len(self)

            return self.xrange[item]

        if type(item) is slice:
            # get the indexes, and then convert to the number
            start, stop, step = item.start, item.stop, item.step
            start = start if start != None else 0 # convert start = None to start = 0
            if start < 0:
                start += start
            start = self[start]
            if start < 0: raise IndexError(item)
            step = (self.step if self.step != None else 1) * (step if step != None else 1)
            stop = stop if stop is not None else self.xrange[-1]
            if stop < 0:
                stop += stop

            stop = self[stop]
            stop = stop

            if stop > self.stop:
                raise IndexError
            if start < self.start:
                raise IndexError
            return Xrange(start, stop, step)

    def index(self, value):
        error = ValueError('object.index({0}): {0} not in object'.format(value))
        index = (value - self.start)/self.step
        if index % 1 != 0:
            raise error
        index = int(index)


        try:
            self.xrange[index]
        except (IndexError, TypeError):
            raise error
        return index

    def __len__(self):
        return len(self.xrange)

Honestly, I think the whole issue is kind of silly and xrange should do all of this anyway…


回答 7

书中的一个很好的例子:Magnus Lie Hetland的《实用Python》

>>> zip(range(5), xrange(100000000))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]

我不建议在前面的示例中使用range而不是xrange -尽管只需要前五个数字,但range会计算所有数字,这可能会花费很多时间。使用xrange,这不是问题,因为它仅计算所需的那些数字。

是的,我读了@Brian的答案:在python 3中,无论如何range()都是生成器,而xrange()不存在。

A good example given in book: Practical Python By Magnus Lie Hetland

>>> zip(range(5), xrange(100000000))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]

I wouldn’t recommend using range instead of xrange in the preceding example—although only the first five numbers are needed, range calculates all the numbers, and that may take a lot of time. With xrange, this isn’t a problem because it calculates only those numbers needed.

Yes I read @Brian’s answer: In python 3, range() is a generator anyway and xrange() does not exist.


回答 8

出于以下原因选择范围:

1)xrange将在较新的Python版本中消失。这样可以轻松实现将来的兼容性。

2)range将承担与xrange相关的效率。

Go with range for these reasons:

1) xrange will be going away in newer Python versions. This gives you easy future compatibility.

2) range will take on the efficiencies associated with xrange.


回答 9

好的,对于xrange与range的权衡和优势,每个人都有不同的看法。它们大体上是正确的,xrange是一个迭代器,range充实并创建实际列表。在大多数情况下,您不会真正注意到两者之间的差异。(您可以将map与range一起使用,但不能与xrange一起使用,但是会占用更多内存。)

但是,我认为您希望聚会中听到的是,首选是xrange。由于Python 3中的range是一个迭代器,因此代码转换工具2to3可以将xrange的所有用法正确转换为range,并且会针对range的使用抛出错误或警告。如果要确保将来轻松转换代码,则仅使用xrange,并在确定需要列表时使用list(xrange)。我是在今年(2008年)在芝加哥PyCon上进行的CPython冲刺中学到的。

Okay, everyone here as a different opinion as to the tradeoffs and advantages of xrange versus range. They’re mostly correct, xrange is an iterator, and range fleshes out and creates an actual list. For the majority of cases, you won’t really notice a difference between the two. (You can use map with range but not with xrange, but it uses up more memory.)

What I think you rally want to hear, however, is that the preferred choice is xrange. Since range in Python 3 is an iterator, the code conversion tool 2to3 will correctly convert all uses of xrange to range, and will throw out an error or warning for uses of range. If you want to be sure to easily convert your code in the future, you’ll use xrange only, and list(xrange) when you’re sure that you want a list. I learned this during the CPython sprint at PyCon this year (2008) in Chicago.


回答 10

  • range()range(1, 10)返回1到10个数字的列表,并将整个列表保存在内存中。
  • xrange():和一样range(),但不返回列表,而是返回一个对象,该对象根据需要生成范围内的数字。对于循环,这比速度快一点,range()并且内存效率更高。xrange()像迭代器这样的对象,并按需生成数字(惰性评估)。
In [1]: range(1,10)
Out[1]: [1, 2, 3, 4, 5, 6, 7, 8, 9]

In [2]: xrange(10)
Out[2]: xrange(10)

In [3]: print xrange.__doc__
Out[3]: xrange([start,] stop[, step]) -> xrange object

range()xrange()执行与Python 3中相同的操作,并且在Python 3中不xrange()存在术语。 range()如果多次迭代同一序列,在某些情况下实际上可以更快。xrange()每次都必须重新构造整数对象,但是range()将拥有真正的整数对象。

  • range(): range(1, 10) returns a list from 1 to 10 numbers & hold whole list in memory.
  • xrange(): Like range(), but instead of returning a list, returns an object that generates the numbers in the range on demand. For looping, this is lightly faster than range() and more memory efficient. xrange() object like an iterator and generates the numbers on demand (Lazy Evaluation).
In [1]: range(1,10)
Out[1]: [1, 2, 3, 4, 5, 6, 7, 8, 9]

In [2]: xrange(10)
Out[2]: xrange(10)

In [3]: print xrange.__doc__
Out[3]: xrange([start,] stop[, step]) -> xrange object

range() does the same thing as xrange() used to do in Python 3 and there is not term xrange() exist in Python 3. range() can actually be faster in some scenario if you iterating over the same sequence multiple times. xrange() has to reconstruct the integer object every time, but range() will have real integer objects.


回答 11

虽然xrangerange大多数情况下要快,但性能差异却很小。下面的小程序比较了对a range和an的迭代xrange

import timeit
# Try various list sizes.
for list_len in [1, 10, 100, 1000, 10000, 100000, 1000000]:
  # Time doing a range and an xrange.
  rtime = timeit.timeit('a=0;\nfor n in range(%d): a += n'%list_len, number=1000)
  xrtime = timeit.timeit('a=0;\nfor n in xrange(%d): a += n'%list_len, number=1000)
  # Print the result
  print "Loop list of len %d: range=%.4f, xrange=%.4f"%(list_len, rtime, xrtime)

下面的结果显示xrange确实更快,但不足以使工作过度。

Loop list of len 1: range=0.0003, xrange=0.0003
Loop list of len 10: range=0.0013, xrange=0.0011
Loop list of len 100: range=0.0068, xrange=0.0034
Loop list of len 1000: range=0.0609, xrange=0.0438
Loop list of len 10000: range=0.5527, xrange=0.5266
Loop list of len 100000: range=10.1666, xrange=7.8481
Loop list of len 1000000: range=168.3425, xrange=155.8719

因此,请务必使用xrange,但是除非您使用的是受限制的硬件,否则不要为它担心太多。

While xrange is faster than range in most circumstances, the difference in performance is pretty minimal. The little program below compares iterating over a range and an xrange:

import timeit
# Try various list sizes.
for list_len in [1, 10, 100, 1000, 10000, 100000, 1000000]:
  # Time doing a range and an xrange.
  rtime = timeit.timeit('a=0;\nfor n in range(%d): a += n'%list_len, number=1000)
  xrtime = timeit.timeit('a=0;\nfor n in xrange(%d): a += n'%list_len, number=1000)
  # Print the result
  print "Loop list of len %d: range=%.4f, xrange=%.4f"%(list_len, rtime, xrtime)

The results below shows that xrange is indeed faster, but not enough to sweat over.

Loop list of len 1: range=0.0003, xrange=0.0003
Loop list of len 10: range=0.0013, xrange=0.0011
Loop list of len 100: range=0.0068, xrange=0.0034
Loop list of len 1000: range=0.0609, xrange=0.0438
Loop list of len 10000: range=0.5527, xrange=0.5266
Loop list of len 100000: range=10.1666, xrange=7.8481
Loop list of len 1000000: range=168.3425, xrange=155.8719

So by all means use xrange, but unless you’re on a constrained hardware, don’t worry too much about it.


Python 2.X中的range和xrange函数之间有什么区别?

问题:Python 2.X中的range和xrange函数之间有什么区别?

显然,xrange更快,但是我不知道为什么它更快(到目前为止,除了轶事之外,还没有证据表明它更快)或除此之外还有什么不同

for i in range(0, 20):
for i in xrange(0, 20):

Apparently xrange is faster but I have no idea why it’s faster (and no proof besides the anecdotal so far that it is faster) or what besides that is different about

for i in range(0, 20):
for i in xrange(0, 20):

回答 0

在Python 2.x中:

  • range创建一个列表,所以如果您这样做range(1, 10000000),则会在内存中创建一个包含9999999元素的列表。

  • xrange 是一个延迟计算的序列对象。

在Python 3中,range它等效于python xrange,并且必须使用来获取列表list(range(...))

In Python 2.x:

  • range creates a list, so if you do range(1, 10000000) it creates a list in memory with 9999999 elements.

  • xrange is a sequence object that evaluates lazily.

In Python 3, range does the equivalent of python’s xrange, and to get the list, you have to use list(range(...)).


回答 1

range会创建一个列表,因此,如果执行range(1, 10000000)此操作,则会在内存中创建一个包含9999999元素的列表。

xrange 是一个生成器,所以它是一个序列对象,是一个懒惰求值的对象。

的确如此,但是在Python 3中,.range()将由Python 2实现.xrange()。如果需要实际生成列表,则需要执行以下操作:

list(range(1,100))

range creates a list, so if you do range(1, 10000000) it creates a list in memory with 9999999 elements.

xrange is a generator, so it is a sequence object is a that evaluates lazily.

This is true, but in Python 3, .range() will be implemented by the Python 2 .xrange(). If you need to actually generate the list, you will need to do:

list(range(1,100))

回答 2

记住,使用该timeit模块来测试较小的代码片段更快!

$ python -m timeit 'for i in range(1000000):' ' pass'
10 loops, best of 3: 90.5 msec per loop
$ python -m timeit 'for i in xrange(1000000):' ' pass'
10 loops, best of 3: 51.1 msec per loop

就个人而言,.range()除非我处理的列表非常庞大,否则我总是使用-从时间上可以看出,对于一百万个条目的列表,额外的开销只有0.04秒。正如Corey所指出的那样,在Python 3.0中,它.xrange()将会消失,并且.range()无论如何都会为您提供良好的迭代器行为。

Remember, use the timeit module to test which of small snippets of code is faster!

$ python -m timeit 'for i in range(1000000):' ' pass'
10 loops, best of 3: 90.5 msec per loop
$ python -m timeit 'for i in xrange(1000000):' ' pass'
10 loops, best of 3: 51.1 msec per loop

Personally, I always use .range(), unless I were dealing with really huge lists — as you can see, time-wise, for a list of a million entries, the extra overhead is only 0.04 seconds. And as Corey points out, in Python 3.0 .xrange() will go away and .range() will give you nice iterator behavior anyway.


回答 3

xrange仅存储范围参数并按需生成数字。但是,Python的C实现当前将其args限制为C long:

xrange(2**32-1, 2**32+1)  # When long is 32 bits, OverflowError: Python int too large to convert to C long
range(2**32-1, 2**32+1)   # OK --> [4294967295L, 4294967296L]

请注意,在Python 3.0中仅存在,range并且其行为类似于2.x,xrange但对最小和最大端点没有限制。

xrange only stores the range params and generates the numbers on demand. However the C implementation of Python currently restricts its args to C longs:

xrange(2**32-1, 2**32+1)  # When long is 32 bits, OverflowError: Python int too large to convert to C long
range(2**32-1, 2**32+1)   # OK --> [4294967295L, 4294967296L]

Note that in Python 3.0 there is only range and it behaves like the 2.x xrange but without the limitations on minimum and maximum end points.


回答 4

xrange返回一个迭代器,一次只在内存中保留一个数字。range将整个数字列表保留在内存中。

xrange returns an iterator and only keeps one number in memory at a time. range keeps the entire list of numbers in memory.


回答 5

一定要花一些时间在图书馆参考上。您越熟悉它,就可以更快地找到此类问题的答案。关于内置对象和类型的前几章特别重要。

xrange类型的优点在于,无论xrange对象代表的范围大小如何,它始终将占用相同的内存量。没有一致的性能优势。

查找有关Python构造的快速信息的另一种方法是docstring和help-function:

print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)

Do spend some time with the Library Reference. The more familiar you are with it, the faster you can find answers to questions like this. Especially important are the first few chapters about builtin objects and types.

The advantage of the xrange type is that an xrange object will always take the same amount of memory, no matter the size of the range it represents. There are no consistent performance advantages.

Another way to find quick information about a Python construct is the docstring and the help-function:

print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)

回答 6

我很震惊,没有人读doc

此函数非常类似于range(),但是返回一个xrange对象而不是一个列表。这是一种不透明的序列类型,其产生的值与对应的列表相同,而实际上并没有同时存储它们。xrange()over 的优点range()是最小的(因为xrange()在要求输入值时仍必须创建值),除非在内存不足的计算机上使用了非常大的范围或从未使用过范围的所有元素时(例如当循环被使用时)。通常以break)终止。

I am shocked nobody read doc:

This function is very similar to range(), but returns an xrange object instead of a list. This is an opaque sequence type which yields the same values as the corresponding list, without actually storing them all simultaneously. The advantage of xrange() over range() is minimal (since xrange() still has to create the values when asked for them) except when a very large range is used on a memory-starved machine or when all of the range’s elements are never used (such as when the loop is usually terminated with break).


回答 7

range创建一个列表,因此如果执行range(1,10000000),它将在内存中创建一个包含10000000个元素的列表。xrange是一个生成器,因此它懒惰地求值。

这为您带来两个优点:

  1. 您可以迭代更长的列表而无需获取MemoryError
  2. 当它懒散地解析每个数字时,如果您尽早停止迭代,您将不会浪费时间创建整个列表。

range creates a list, so if you do range(1, 10000000) it creates a list in memory with 10000000 elements. xrange is a generator, so it evaluates lazily.

This brings you two advantages:

  1. You can iterate longer lists without getting a MemoryError.
  2. As it resolves each number lazily, if you stop iteration early, you won’t waste time creating the whole list.

回答 8

在这个简单的示例中,您将发现xrangeover 的优点range

import timeit

t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
    pass
t2 = timeit.default_timer()

print "time taken: ", (t2-t1)  # 4.49153590202 seconds

t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
    pass
t2 = timeit.default_timer()

print "time taken: ", (t2-t1)  # 7.04547905922 seconds

上面的示例在的情况下并没有任何实质性的改善xrange

现在range,与相比,以下情况的确非常慢xrange

import timeit

t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
    if i == 10000:
        break
t2 = timeit.default_timer()

print "time taken: ", (t2-t1)  # 0.000764846801758 seconds

t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
    if i == 10000:
        break
t2 = timeit.default_timer() 

print "time taken: ", (t2-t1)  # 2.78506207466 seconds

使用range,它已经创建了一个从0到100000000(耗时)的列表,但是它xrange是一个生成器,并且仅根据需要(即,如果继续迭代)生成数字。

在Python-3中,该range功能的实现与xrangePython-2中的相同,而xrange在Python-3中已取消了该功能。

快乐编码!

You will find the advantage of xrange over range in this simple example:

import timeit

t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
    pass
t2 = timeit.default_timer()

print "time taken: ", (t2-t1)  # 4.49153590202 seconds

t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
    pass
t2 = timeit.default_timer()

print "time taken: ", (t2-t1)  # 7.04547905922 seconds

The above example doesn’t reflect anything substantially better in case of xrange.

Now look at the following case where range is really really slow, compared to xrange.

import timeit

t1 = timeit.default_timer()
a = 0
for i in xrange(1, 100000000):
    if i == 10000:
        break
t2 = timeit.default_timer()

print "time taken: ", (t2-t1)  # 0.000764846801758 seconds

t1 = timeit.default_timer()
a = 0
for i in range(1, 100000000):
    if i == 10000:
        break
t2 = timeit.default_timer() 

print "time taken: ", (t2-t1)  # 2.78506207466 seconds

With range, it already creates a list from 0 to 100000000(time consuming), but xrange is a generator and it only generates numbers based on the need, that is, if the iteration continues.

In Python-3, the implementation of the range functionality is same as that of xrange in Python-2, while they have done away with xrange in Python-3

Happy Coding!!


回答 9

这是出于优化的原因。

range()将从头到尾创建一个值列表(在您的示例中为0 .. 20)。在很大范围内,这将成为昂贵的操作。

另一方面,xrange()更优化了。它只会在需要时(通过xrange序列对象)计算下一个值,并且不会像range()那样创建所有值的列表。

It is for optimization reasons.

range() will create a list of values from start to end (0 .. 20 in your example). This will become an expensive operation on very large ranges.

xrange() on the other hand is much more optimised. it will only compute the next value when needed (via an xrange sequence object) and does not create a list of all values like range() does.


回答 10

range(x,y)如果使用for循环,则返回x和y之间的每个数字的列表,这样range比较慢。实际上,range具有较大的Index范围。range(x.y)将打印出x和y之间所有数字的列表

xrange(x,y)返回,xrange(x,y)但如果使用for循环,则xrange速度更快。xrange索引范围较小。xrange不仅会打印出来xrange(x,y),还会保留其中的所有数字。

[In] range(1,10)
[Out] [1, 2, 3, 4, 5, 6, 7, 8, 9]
[In] xrange(1,10)
[Out] xrange(1,10)

如果使用for循环,那么它将起作用

[In] for i in range(1,10):
        print i
[Out] 1
      2
      3
      4
      5
      6
      7
      8
      9
[In] for i in xrange(1,10):
         print i
[Out] 1
      2
      3
      4
      5
      6
      7
      8
      9

尽管使用循环时并没有什么不同,但仅打印循环时也有差异!

range(x,y) returns a list of each number in between x and y if you use a for loop, then range is slower. In fact, range has a bigger Index range. range(x.y) will print out a list of all the numbers in between x and y

xrange(x,y) returns xrange(x,y) but if you used a for loop, then xrange is faster. xrange has a smaller Index range. xrange will not only print out xrange(x,y) but it will still keep all the numbers that are in it.

[In] range(1,10)
[Out] [1, 2, 3, 4, 5, 6, 7, 8, 9]
[In] xrange(1,10)
[Out] xrange(1,10)

If you use a for loop, then it would work

[In] for i in range(1,10):
        print i
[Out] 1
      2
      3
      4
      5
      6
      7
      8
      9
[In] for i in xrange(1,10):
         print i
[Out] 1
      2
      3
      4
      5
      6
      7
      8
      9

There isn’t much difference when using loops, though there is a difference when just printing it!


回答 11

range(): range(1,10)返回一个1到10个数字的列表,并将整个列表保存在内存中。

xrange():类似于range(),但不返回列表,而是返回一个对象,该对象根据需要生成范围内的数字。对于循环,这比range()快一点,并且内存效率更高。xrange()对象就像一个迭代器,并根据需要生成数字。(延迟评估)

In [1]: range(1,10)

Out[1]: [1, 2, 3, 4, 5, 6, 7, 8, 9]

In [2]: xrange(10)

Out[2]: xrange(10)

In [3]: print xrange.__doc__

xrange([start,] stop[, step]) -> xrange object

range(): range(1, 10) returns a list from 1 to 10 numbers & hold whole list in memory.

xrange(): Like range(), but instead of returning a list, returns an object that generates the numbers in the range on demand. For looping, this is lightly faster than range() and more memory efficient. xrange() object like an iterator and generates the numbers on demand.(Lazy Evaluation)

In [1]: range(1,10)

Out[1]: [1, 2, 3, 4, 5, 6, 7, 8, 9]

In [2]: xrange(10)

Out[2]: xrange(10)

In [3]: print xrange.__doc__

xrange([start,] stop[, step]) -> xrange object

回答 12

其他一些答案提到Python 3淘汰了2.x range,并将2.x重命名xrangerange。但是,除非您使用3.0或3.1(应该没有人使用),否则它实际上是一种不同的类型。

正如3.1文档所说:

范围对象几乎没有行为:它们仅支持索引,迭代和len功能。

但是,在3.2+版本中,它range是一个完整序列,它支持扩展的slice,以及所有collections.abc.Sequence与语义相同的方法list*

并且,至少在CPython和PyPy(当前仅有的两个3.2+实现)中,它还具有indexand count方法和in运算符的恒定时间实现(只要您仅将其传递为整数)。这意味着123456 in r在3.2+版本中写作是合理的,而在2.7或3.1版本中这将是一个可怕的想法。


*事实上,issubclass(xrange, collections.Sequence)回报率True在2.6-2.7 3.0-3.1和是一个错误是固定在3.2,而不是向后移植。

Some of the other answers mention that Python 3 eliminated 2.x’s range and renamed 2.x’s xrange to range. However, unless you’re using 3.0 or 3.1 (which nobody should be), it’s actually a somewhat different type.

As the 3.1 docs say:

Range objects have very little behavior: they only support indexing, iteration, and the len function.

However, in 3.2+, range is a full sequence—it supports extended slices, and all of the methods of collections.abc.Sequence with the same semantics as a list.*

And, at least in CPython and PyPy (the only two 3.2+ implementations that currently exist), it also has constant-time implementations of the index and count methods and the in operator (as long as you only pass it integers). This means writing 123456 in r is reasonable in 3.2+, while in 2.7 or 3.1 it would be a horrible idea.


* The fact that issubclass(xrange, collections.Sequence) returns True in 2.6-2.7 and 3.0-3.1 is a bug that was fixed in 3.2 and not backported.


回答 13

在python 2.x中

range(x)返回一个列表,该列表在内存中创建有x个元素。

>>> a = range(5)
>>> a
[0, 1, 2, 3, 4]

xrange(x)返回一个xrange对象,该对象是生成器obj,可按需生成数字。它们是在for循环(惰性评估)期间计算的。

对于循环,这比range()快一点,并且内存效率更高。

>>> b = xrange(5)
>>> b
xrange(5)

In python 2.x

range(x) returns a list, that is created in memory with x elements.

>>> a = range(5)
>>> a
[0, 1, 2, 3, 4]

xrange(x) returns an xrange object which is a generator obj which generates the numbers on demand. they are computed during for-loop(Lazy Evaluation).

For looping, this is slightly faster than range() and more memory efficient.

>>> b = xrange(5)
>>> b
xrange(5)

回答 14

在循环中针对xrange测试范围时(我知道我应该使用timeit,但是使用简单的列表理解示例从内存中迅速破解了它),我发现了以下内容:

import time

for x in range(1, 10):

    t = time.time()
    [v*10 for v in range(1, 10000)]
    print "range:  %.4f" % ((time.time()-t)*100)

    t = time.time()
    [v*10 for v in xrange(1, 10000)]
    print "xrange: %.4f" % ((time.time()-t)*100)

这使:

$python range_tests.py
range:  0.4273
xrange: 0.3733
range:  0.3881
xrange: 0.3507
range:  0.3712
xrange: 0.3565
range:  0.4031
xrange: 0.3558
range:  0.3714
xrange: 0.3520
range:  0.3834
xrange: 0.3546
range:  0.3717
xrange: 0.3511
range:  0.3745
xrange: 0.3523
range:  0.3858
xrange: 0.3997 <- garbage collection?

或者,在for循环中使用xrange:

range:  0.4172
xrange: 0.3701
range:  0.3840
xrange: 0.3547
range:  0.3830
xrange: 0.3862 <- garbage collection?
range:  0.4019
xrange: 0.3532
range:  0.3738
xrange: 0.3726
range:  0.3762
xrange: 0.3533
range:  0.3710
xrange: 0.3509
range:  0.3738
xrange: 0.3512
range:  0.3703
xrange: 0.3509

我的代码段测试是否正确?对较慢的xrange实例有何评论?或更好的例子:-)

When testing range against xrange in a loop (I know I should use timeit, but this was swiftly hacked up from memory using a simple list comprehension example) I found the following:

import time

for x in range(1, 10):

    t = time.time()
    [v*10 for v in range(1, 10000)]
    print "range:  %.4f" % ((time.time()-t)*100)

    t = time.time()
    [v*10 for v in xrange(1, 10000)]
    print "xrange: %.4f" % ((time.time()-t)*100)

which gives:

$python range_tests.py
range:  0.4273
xrange: 0.3733
range:  0.3881
xrange: 0.3507
range:  0.3712
xrange: 0.3565
range:  0.4031
xrange: 0.3558
range:  0.3714
xrange: 0.3520
range:  0.3834
xrange: 0.3546
range:  0.3717
xrange: 0.3511
range:  0.3745
xrange: 0.3523
range:  0.3858
xrange: 0.3997 <- garbage collection?

Or, using xrange in the for loop:

range:  0.4172
xrange: 0.3701
range:  0.3840
xrange: 0.3547
range:  0.3830
xrange: 0.3862 <- garbage collection?
range:  0.4019
xrange: 0.3532
range:  0.3738
xrange: 0.3726
range:  0.3762
xrange: 0.3533
range:  0.3710
xrange: 0.3509
range:  0.3738
xrange: 0.3512
range:  0.3703
xrange: 0.3509

Is my snippet testing properly? Any comments on the slower instance of xrange? Or a better example :-)


回答 15

python中的xrange()和range()与用户的工作原理相似,但是区别在于,当我们讨论使用这两个函数分配内存的方式时。

当我们使用range()时,我们为它生成的所有变量分配内存,因此不建议使用更大的no。生成的变量。

另一方面,xrange()一次仅生成一个特定值,并且只能与for循环一起使用以打印所需的所有值。

xrange() and range() in python works similarly as for the user , but the difference comes when we are talking about how the memory is allocated in using both the function.

When we are using range() we allocate memory for all the variables it is generating, so it is not recommended to use with larger no. of variables to be generated.

xrange() on the other hand generate only a particular value at a time and can only be used with the for loop to print all the values required.


回答 16

range生成整个列表并返回。xrange不会-它会按需生成列表中的数字。

range generates the entire list and returns it. xrange does not — it generates the numbers in the list on demand.


回答 17

xrange使用迭代器(动态生成值),range返回一个列表。

xrange uses an iterator (generates values on the fly), range returns a list.


回答 18

什么?
range在运行时返回静态列表。
xrange返回一个object(在某种情况下,它的作用类似于生成器,尽管肯定不是一个),并在需要时从中生成值。

什么时候使用?

  • xrange如果要生成一个巨大范围(例如10亿)的列表,则可以使用该选项,尤其是当您拥有像手机这样的“内存敏感系统”时。
  • 使用range,如果你想在列表几次迭代。

PS:Python 3.x的range功能== Python 2.x的xrange功能。

What?
range returns a static list at runtime.
xrange returns an object (which acts like a generator, although it’s certainly not one) from which values are generated as and when required.

When to use which?

  • Use xrange if you want to generate a list for a gigantic range, say 1 billion, especially when you have a “memory sensitive system” like a cell phone.
  • Use range if you want to iterate over the list several times.

PS: Python 3.x’s range function == Python 2.x’s xrange function.


回答 19

每个人都对此做了很大的解释。但我希望自己看到它。我使用python3。因此,我打开了资源监视器(在Windows中!),首先,首先执行以下命令:

a=0
for i in range(1,100000):
    a=a+i

然后检查“使用中”内存中的更改。这无关紧要。然后,我运行了以下代码:

for i in list(range(1,100000)):
    a=a+i

立即消耗了很大一部分内存。而且,我被说服了。您可以自己尝试。

如果您使用的是Python 2X,则在第一个代码中将“ range()”替换为“ xrange()”,将“ list(range())”替换为“ range()”。

Everyone has explained it greatly. But I wanted it to see it for myself. I use python3. So, I opened the resource monitor (in Windows!), and first, executed the following command first:

a=0
for i in range(1,100000):
    a=a+i

and then checked the change in ‘In Use’ memory. It was insignificant. Then, I ran the following code:

for i in list(range(1,100000)):
    a=a+i

And it took a big chunk of the memory for use, instantly. And, I was convinced. You can try it for yourself.

If you are using Python 2X, then replace ‘range()’ with ‘xrange()’ in the first code and ‘list(range())’ with ‘range()’.


回答 20

从帮助文档。

Python 2.7.12

>>> print range.__doc__
range(stop) -> list of integers
range(start, stop[, step]) -> list of integers

Return a list containing an arithmetic progression of integers.
range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
When step is given, it specifies the increment (or decrement).
For example, range(4) returns [0, 1, 2, 3].  The end point is omitted!
These are exactly the valid indices for a list of 4 elements.

>>> print xrange.__doc__
xrange(stop) -> xrange object
xrange(start, stop[, step]) -> xrange object

Like range(), but instead of returning a list, returns an object that
generates the numbers in the range on demand.  For looping, this is 
slightly faster than range() and more memory efficient.

Python 3.5.2

>>> print(range.__doc__)
range(stop) -> range object
range(start, stop[, step]) -> range object

Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).

>>> print(xrange.__doc__)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'xrange' is not defined

差异显而易见。在Python 2.x中,range返回一个列表,xrange返回一个可迭代的xrange对象。

在Python 3.x中,range成为xrangePython 2.x并被xrange删除。

From the help docs.

Python 2.7.12

>>> print range.__doc__
range(stop) -> list of integers
range(start, stop[, step]) -> list of integers

Return a list containing an arithmetic progression of integers.
range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
When step is given, it specifies the increment (or decrement).
For example, range(4) returns [0, 1, 2, 3].  The end point is omitted!
These are exactly the valid indices for a list of 4 elements.

>>> print xrange.__doc__
xrange(stop) -> xrange object
xrange(start, stop[, step]) -> xrange object

Like range(), but instead of returning a list, returns an object that
generates the numbers in the range on demand.  For looping, this is 
slightly faster than range() and more memory efficient.

Python 3.5.2

>>> print(range.__doc__)
range(stop) -> range object
range(start, stop[, step]) -> range object

Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).

>>> print(xrange.__doc__)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'xrange' is not defined

Difference is apparent. In Python 2.x, range returns a list, xrange returns an xrange object which is iterable.

In Python 3.x, range becomes xrange of Python 2.x, and xrange is removed.


回答 21

根据扫描/打印0-N个项目的要求,range和xrange的工作方式如下。

range()-在内存中创建一个新列表,并将整个0到N个项目(总共N + 1个)打印出来。xrange()-创建一个迭代器实例,该实例扫描项目并仅将当前遇到的项目保留在内存中,因此始终使用相同数量的内存。

如果所需元素只是在列表的开头,那么它可以节省大量时间和内存。

On a requirement for scanning/printing of 0-N items , range and xrange works as follows.

range() – creates a new list in the memory and takes the whole 0 to N items(totally N+1) and prints them. xrange() – creates a iterator instance that scans through the items and keeps only the current encountered item into the memory , hence utilising same amount of memory all the time.

In case the required element is somewhat at the beginning of the list only then it saves a good amount of time and memory.


回答 22

Range返回一个列表,xrange返回一个xrange对象,无论范围大小如何,该对象都占用相同的内存,因为在这种情况下,每次迭代仅生成一个元素并且可用,而在使用range的情况下,所有元素一次生成,并且在内存中可用。

Range returns a list while xrange returns an xrange object which takes the same memory irrespective of the range size,as in this case,only one element is generated and available per iteration whereas in case of using range, all the elements are generated at once and are available in the memory.


回答 23

对于较小的参数差减小range(..)/ xrange(..)

$ python -m timeit "for i in xrange(10111):" " for k in range(100):" "  pass"
10 loops, best of 3: 59.4 msec per loop

$ python -m timeit "for i in xrange(10111):" " for k in xrange(100):" "  pass"
10 loops, best of 3: 46.9 msec per loop

在这种情况下,xrange(100)效率仅提高约20%。

The difference decreases for smaller arguments to range(..) / xrange(..):

$ python -m timeit "for i in xrange(10111):" " for k in range(100):" "  pass"
10 loops, best of 3: 59.4 msec per loop

$ python -m timeit "for i in xrange(10111):" " for k in xrange(100):" "  pass"
10 loops, best of 3: 46.9 msec per loop

In this case xrange(100) is only about 20% more efficient.


回答 24

range:-range会立即填充所有内容,这意味着范围的每个数字都会占用内存。

xrange:-xrange类似于生成器,当您想要数字的范围但不希望将它们存储时(例如当您要在for loop.so中使用时),它将出现在图片中,这样可以提高内存效率。

range :-range will populate everything at once.which means every number of the range will occupy the memory.

xrange :-xrange is something like generator ,it will comes into picture when you want the range of numbers but you dont want them to be stored,like when you want to use in for loop.so memory efficient.


回答 25

此外,如果这样做list(xrange(...))等同于range(...)

所以 list很慢。

xrange真的没有完全完成序列

这就是为什么它不是列表,而是xrange对象

Additionally, if do list(xrange(...)) will be equivalent to range(...).

So list is slow.

Also xrange really doesn’t fully finish the sequence

So that’s why its not a list, it’s a xrange object


回答 26

range() 在Python中 2.x

此函数本质range()上是Python中可用的旧函数,它2.x返回list包含指定范围内的元素的对象的实例。

但是,这种实现在初始化带有一系列数字的列表时效率太低。例如,for i in range(1000000)就内存和时间使用而言,要执行的命令非常昂贵,因为它需要将此列表存储到内存中。


range()在Python 3.xxrange()Python中2.x

Python 3.x引入了更新的实现range()(而更新的实现已经可以2.x通过Python 通过xrange()功能)。

range()漏洞利用一种称为惰性评估的策略较新的实现未在范围内创建大量元素,而是引入了class range,这是一个轻量级的对象,代表给定范围内的所需元素,而无需将其显式存储在内存中(这听起来像是生成器,但是惰性求值的概念是不同)。


例如,请考虑以下内容:

# Python 2.x
>>> a = range(10)
>>> type(a)
<type 'list'>
>>> b = xrange(10)
>>> type(b)
<type 'xrange'>

# Python 3.x
>>> a = range(10)
>>> type(a)
<class 'range'>

range() in Python 2.x

This function is essentially the old range() function that was available in Python 2.x and returns an instance of a list object that contains the elements in the specified range.

However, this implementation is too inefficient when it comes to initialise a list with a range of numbers. For example, for i in range(1000000) would be a very expensive command to execute, both in terms of memory and time usage as it requires the storage of this list into the memory.


range() in Python 3.x and xrange() in Python 2.x

Python 3.x introduced a newer implementation of range() (while the newer implementation was already available in Python 2.x through the xrange() function).

The range() exploits a strategy known as lazy evaluation. Instead of creating a huge list of elements in range, the newer implementation introduces the class range, a lightweight object that represents the required elements in the given range, without storing them explicitly in memory (this might sound like generators but the concept of lazy evaluation is different).


As an example, consider the following:

# Python 2.x
>>> a = range(10)
>>> type(a)
<type 'list'>
>>> b = xrange(10)
>>> type(b)
<type 'xrange'>

and

# Python 3.x
>>> a = range(10)
>>> type(a)
<class 'range'>

回答 27

看到这个帖子以查找range和xrange之间的区别:

报价:

range返回确切的结果:一系列连续的整数,定义的长度以0开头xrange。但是,将返回“ xrange object”,其作用类似于迭代器

See this post to find difference between range and xrange:

To quote:

range returns exactly what you think: a list of consecutive integers, of a defined length beginning with 0. xrange, however, returns an “xrange object”, which acts a great deal like an iterator