[python] range ()보다 항상 xrange ()를 선호해야합니까?

그 이유는 무엇?



답변

특히 넓은 범위에서 반복 할 때 성능 xrange()이 더 좋습니다. 그러나 여전히 선호하는 몇 가지 경우가 있습니다 range().

  • 파이썬 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 ()로 래핑 된 경우 범위는 변경되지 않습니다.


답변

아니요, 둘 다 용도가 있습니다.

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


답변

당신은 선호합니다 range()이상 xrange()이 실제 목록이 필요합니다 경우에만 사용할 수 있습니다. 예를 들어,에서 반환 한 목록을 수정하려는 경우 range()또는 슬라이스하려는 경우입니다. 반복 또는 심지어 정상적인 색인 xrange()작업의 경우 잘 작동합니다 (보통 훨씬 더 효율적으로). 아주 작은 목록 range()보다 약간 더 빠른 지점 이 xrange()있지만 하드웨어 및 기타 다양한 세부 사항에 따라 손익 분기는 길이 1 또는 2의 결과 일 수 있습니다. 걱정할 것이 없습니다. 선호 xrange()합니다.


답변

또 다른 차이점은 xrange ()는 C ints보다 큰 숫자를 지원할 수 없다는 점입니다. 따라서 파이썬의 많은 수의 지원을 사용하여 범위를 원하면 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

파이썬 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)


답변

xrange()객체 목록을 생성하는 대신 한 번에 하나의 객체 만 생성하기 때문에 더 효율적입니다. 100 개의 정수와 모든 오버 헤드와 그것들을 넣을 목록 대신 한 번에 하나의 정수만 있습니다. 더 빠른 생성, 더 나은 메모리 사용, 더 효율적인 코드.

내가 특별히 목록을 필요로하지 않는 한, 항상 선호 xrange()


답변

range ()는 목록을 반환하고 xrange ()는 xrange 객체를 반환합니다.

xrange ()는 약간 빠르며 약간 더 메모리 효율적입니다. 그러나 이익은 그리 크지 않습니다.

리스트가 사용하는 여분의 메모리는 물론 낭비되지 않고리스트는 더 많은 기능 (슬라이스, 반복, 삽입 등)을 갖습니다. 정확한 차이점은 설명서 에서 찾을 수 있습니다 . 기본 규칙이 없으므로 필요한 것을 사용하십시오.

Python 3.0은 아직 개발 중이지만 IIRC range ()는 xrange () 2.X와 매우 유사하며 list (range ())를 사용하여 목록을 생성 할 수 있습니다.


답변

나는 슬라이스 및 인덱싱 기능을 가진 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는이 모든 것을 어쨌든해야한다고 생각합니다 …