다른 날 파이썬 벤치마킹을하던 중 흥미로운 것을 발견했습니다. 다음은 거의 동일한 작업을 수행하는 두 개의 루프입니다. 루프 1은 실행하는 데 루프 2의 약 두 배가 걸립니다.
루프 1 :
int i = 0
while i < 100000000:
  i += 1
루프 2 :
for n in range(0,100000000):
  pass
첫 번째 루프가 왜 그렇게 느린가요? 나는 그것이 사소한 예라는 것을 알고 있지만 그것은 내 관심을 불러 일으켰습니다. 같은 방식으로 변수를 증가시키는 것보다 더 효율적으로 만드는 range () 함수에 특별한 것이 있습니까?
답변
파이썬 바이트 코드의 분해를 참조하면 더 구체적인 아이디어를 얻을 수 있습니다.
while 루프 사용 :
1           0 LOAD_CONST               0 (0)
            3 STORE_NAME               0 (i)
2           6 SETUP_LOOP              28 (to 37)
      >>    9 LOAD_NAME                0 (i)              # <-
           12 LOAD_CONST               1 (100000000)      # <-
           15 COMPARE_OP               0 (<)              # <-
           18 JUMP_IF_FALSE           14 (to 35)          # <-
           21 POP_TOP                                     # <-
3          22 LOAD_NAME                0 (i)              # <-
           25 LOAD_CONST               2 (1)              # <-
           28 INPLACE_ADD                                 # <-
           29 STORE_NAME               0 (i)              # <-
           32 JUMP_ABSOLUTE            9                  # <-
      >>   35 POP_TOP
           36 POP_BLOCK
루프 본체에는 10 개의 op가 있습니다.
사용 범위 :
1           0 SETUP_LOOP              23 (to 26)
            3 LOAD_NAME                0 (range)
            6 LOAD_CONST               0 (0)
            9 LOAD_CONST               1 (100000000)
           12 CALL_FUNCTION            2
           15 GET_ITER
      >>   16 FOR_ITER                 6 (to 25)        # <-
           19 STORE_NAME               1 (n)            # <-
2          22 JUMP_ABSOLUTE           16                # <-
      >>   25 POP_BLOCK
      >>   26 LOAD_CONST               2 (None)
           29 RETURN_VALUE
루프 본문에는 3 개의 작업이 있습니다.
C 코드를 실행하는 시간은 정수기보다 훨씬 짧으며 무시할 수 있습니다.
답변
range()C로 구현되지만 i += 1해석됩니다.
사용하면 많은 xrange()수의 경우 훨씬 더 빠르게 처리 할 수 있습니다. Python 3.0부터는 range()이전과 동일합니다 xrange().
답변
while 루프에서 많은 객체 생성 및 파괴가 진행되고 있다고 말해야합니다.
i += 1
와 같다:
i = i + 1
그러나 Python int는 불변이기 때문에 기존 객체를 수정하지 않습니다. 오히려 그것은 새로운 가치를 가진 새로운 물건을 창조합니다. 기본적으로 다음과 같습니다.
i = new int(i + 1)   # Using C++ or Java-ish syntax
가비지 수집기는 또한 많은 양의 정리 작업을 수행해야합니다. “객체 생성은 비싸다”.
답변
인터프리터에서 C로 작성된 코드로 더 자주 실행되기 때문입니다. 즉, i + = 1은 Python에 있으므로 (비교적으로) 느리지 만 range (0, …)은 하나의 C 호출이며 for 루프는 대부분 C에서도 실행됩니다.
답변
대부분의 Python의 내장 메서드 호출은 C 코드로 실행됩니다. 해석해야하는 코드는 훨씬 느립니다. 메모리 효율성과 실행 속도 측면에서 그 차이는 엄청납니다. 파이썬 내부는 극도로 최적화되었으며 이러한 최적화를 활용하는 것이 가장 좋습니다.
답변
여기에 대한 대답은 다른 대답이 제안하는 것보다 조금 더 미묘하다고 생각하지만 그 요점은 정확하지만 for 루프는 더 많은 작업이 C에서 발생하고 Python에서는 덜 발생하기 때문에 더 빠릅니다 .
보다 구체적으로, for 루프의 경우 C에서 while 루프에서 Python으로 처리되는 두 가지 일이 발생합니다.
- 
while 루프에서는 비교
i < 100000000가 Python에서 실행되는 반면, for 루프에서는 작업이의 반복자에 전달되어range(100000000)내부적으로 C에서 반복 (따라서 경계 검사)을 수행합니다. - 
while 루프에서 루프 업데이트
i += 1는 Python에서 발생하는 반면 for 루프에서는 다시range(100000000)C로 작성된 의 반복자가i+=1(또는++i)을 수행합니다. 
차이를 확인하기 위해 수동으로 다시 추가하여 for 루프를 더 빠르게 만드는 것이이 두 가지의 조합임을 알 수 있습니다.
import timeit
N = 100000000
def while_loop():
    i = 0
    while i < N:
        i += 1
def for_loop_pure():
    for i in range(N):
        pass
def for_loop_with_increment():
    for i in range(N):
        i += 1
def for_loop_with_test():
    for i in range(N):
        if i < N: pass
def for_loop_with_increment_and_test():
    for i in range(N):
        if i < N: pass
        i += 1
def main():
    print('while loop\t\t', timeit.timeit(while_loop, number=1))
    print('for pure\t\t', timeit.timeit(for_loop_pure, number=1))
    print('for inc\t\t\t', timeit.timeit(for_loop_with_increment, number=1))
    print('for test\t\t', timeit.timeit(for_loop_with_test, number=1))
    print('for inc+test\t', timeit.timeit(for_loop_with_increment_and_test, number=1))
if __name__ == '__main__':
    main()
나는 숫자 100000000 리터럴 상수와 N더 일반적인 변수 인 변수 로 이것을 시도했습니다 .
# inline constant N
while loop      3.5131139
for pure        1.3211338000000001
for inc         3.5477727000000003
for test        2.5209639
for inc+test    4.697028999999999
# variable N
while loop      4.1298240999999996
for pure        1.3526357999999998
for inc         3.6060175
for test        3.1093069
for inc+test    5.4753364
보시다시피 두 경우 모두 while시간은 for inc+test및 의 차이에 매우 가깝습니다 for pure. 또한 N변수를 사용하는 경우 while의 값을 반복적으로 조회하기 위해 추가 속도가 느려지 N지만 for그렇지 않습니다.
이러한 사소한 수정으로 인해 코드 속도가 3 배 이상 빨라진다 는 사실은 정말 미쳤습니다 .하지만 그것은 Python입니다. 그리고 루프를 통해 빌트인을 사용할 수있을 때 시작하지 마십시오 ….
답변
