当前位置:  开发笔记 > 编程语言 > 正文

你是否应该总是偏爱范围()的xrange()?

如何解决《你是否应该总是偏爱范围()的xrange()?》经验,为你挑选了7个好方法。

为什么或者为什么不?



1> Brian..:

对于性能,尤其是当您在大范围内进行迭代时,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()包装的时候,范围保持不变.


你是什​​么意思"范围会变成迭代器"?这应该不是"发电机"吗?
编号生成器是指特定类型的迭代器,而新的`range`无论如何都不是迭代器.

2> Dan Lenski..:

不,他们都有自己的用途:

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



3> Thomas Woute..:

你应该赞成range()xrange()只有当你需要一个实际的名单.例如,当您想要修改返回的列表range()时,或者您希望对其进行切片时.对于迭代甚至只是正常的索引,xrange()将工作正常(通常更有效).有一点range()xrange()非常小的列表快一点,但根据你的硬件和其他各种细节,收支平衡可能是长度为1或2的结果; 不用担心.喜欢xrange().



4> Brian Minton..:

另一个区别是xrange()不能支持大于C int的数字,所以如果你想使用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 "", line 1, in 
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)



5> Dan Udey..:

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

除非我特别需要列表,否则我总是喜欢 xrange()



6> 小智..:

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

xrange()有点快,而且内存效率更高一点.但收益不是很大.

列表使用的额外内存当然不仅仅是浪费,列表具有更多功能(切片,重复,插入,...).可以在文档中找到确切的差异.没有骨科规则,使用所需的东西.

Python 3.0仍处于开发阶段,但IIRC range()与2.X的xrange()非常相似,list(range())可用于生成列表.



7> Garrett Berg..:

我只想说,获得具有切片和索引功能的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应该做所有这些...

推荐阅读
手机用户2502851955
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有