최근에 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
사람들이 같은 것을 몇 번이나 말했는지에 관계없이 왜 제거 되었는지 묻는 질문을 반복하지만 다시 반복하겠습니다. 제거되지 않았습니다. 이름이로 바뀌었고 range
2.x range
가 제거되었습니다.
다음은 3.3 range
객체가 2.x xrange
객체가 아닌 2.x 객체 의 직접적인 자손 이라는 증거입니다 range
. 소스는 3.3range
및 2.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 ()에 비해 속도가 빠릅니다.