[python] Python3에 xrange 함수가없는 이유는 무엇입니까?

최근에 Python3을 사용하기 시작했으며 xrange 상처가 부족합니다.

간단한 예 :

1) 파이썬 2 :

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

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.x는 range실제로 2.x보다 약간 느립니다 xrange. 그리고 OP의 xrange기능은 그것과 관련이 없습니다. ( __iter__슬롯 에 대한 일회성 호출 이 루프에서 발생하는 모든 작업에 대해 10000000 번의 호출 중 보이지 않을 가능성이 있지만 누군가가이를 가능성으로 제기 한 것은 놀라운 일 이 아닙니다.)

그러나 30 % 더 느립니다. 영업 이익은 어떻게 2 배나 느려졌습니까? 글쎄, 32 비트 파이썬으로 동일한 테스트를 반복하면 1.58 대 3.12를 얻습니다. 그래서 이것은 32 비트를 손상시키는 방식으로 3.x가 64 비트 성능에 맞게 최적화 된 경우 중 하나입니다.

하지만 정말 중요합니까? 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전체 반복보다 두 배 이상의 시간이 소요됩니다.

그리고 “파이썬 2.6+보다 훨씬 더 많은 리소스를 소비한다”는 테스트에서 3.x range는 2.x xrange와 정확히 같은 크기 인 것 같습니다. 범위 반복이 할 수있는 것보다 여전히 약 10000000 배 더 많은 문제입니다.

그리고 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사람들이 같은 것을 몇 번이나 말했는지에 관계없이 왜 제거 되었는지 묻는 질문을 반복하지만 다시 반복하겠습니다. 제거되지 않았습니다. 이름이로 바뀌었고 range2.x range가 제거되었습니다.

다음은 3.3 range객체가 2.x xrange객체가 아닌 2.x 객체 의 직접적인 자손 이라는 증거입니다 range. 소스는 3.3range2.7xrange 입니다. 당신은 심지어 변경 내역을 볼 수 있습니다 (파일의 어느 곳에서나 문자열 “xrange”의 마지막 인스턴스를 대체 한 변경 사항에 연결되어 있다고 생각합니다).

왜 느린가요?

글쎄, 그들은 많은 새로운 기능을 추가했습니다. 다른 경우에는 사소한 부작용이있는 모든 장소 (특히 반복 내부)에서 모든 종류의 변경을 수행했습니다. 때로는 덜 중요한 경우를 약간 비관 화하더라도 다양한 중요한 경우를 극적으로 최적화하기위한 많은 작업이있었습니다. 이 모든 것을 합하면 가능한 range한 빨리 반복하는 것이 조금 느리다는 사실에 놀라지 않습니다 . 아무도 그다지 집중하지 않을 정도로 덜 중요한 경우 중 하나입니다. 이 성능 차이가 코드의 핫스팟 인 실제 사용 사례는 없을 것입니다.


답변

Python3의 범위 Python2의 xrange입니다. 주위에 iter를 감쌀 필요가 없습니다. Python3에서 실제 목록을 얻으려면list(range(...))

Python2 및 Python3에서 작동하는 것을 원한다면 이것을 시도하십시오

try:
    xrange
except NameError:
    xrange = range


답변

Python 3의 range유형은 Python 2와 동일하게 작동합니다 xrange. xrange함수에서 반환 된 반복자 가 range직접 반복하면 얻을 수있는 것이기 때문에 왜 느려지는 지 잘 모르겠습니다 .

시스템 속도 저하를 재현 할 수 없습니다. 내가 테스트 한 방법은 다음과 같습니다.

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

내가 최근 파이썬 3의 사실을 알게 range유형은 슬라이스에 대한 지원과 같은 다른 깔끔한 기능을 가지고 range(10,100,2)[5:25:5]있다 range(20, 60, 10)!


답변

python2 코드를 수정하는 한 가지 방법은 다음과 같습니다.

import sys

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


답변

Python 2의 xrange는 생성기이며 iterator를 구현하는 반면 range는 단지 함수입니다. 파이썬 3에서는 왜 xrange에서 빠졌는지 모르겠습니다.


답변

comp : ~ $ python
Python 2.7.6 (디폴트, 2015 년 6 월 22 일, 17:58:13) [linux2의 [GCC 4.8.2]

>>> 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 번호가 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

그래서 우리가 timeit.timeit ( “[x는 x는 x % 4]이면 x (1000000) x, x = x]], number = 1)과 같이 1 개의 실행 루프 사이클을 측정하면 python3은 충분히 빠르게 작동합니다. 그러나 반복 루프에서 파이썬 2 xrange ()는 파이썬 3의 range ()에 비해 속도가 빠릅니다.


답변