[python] while (1) vs. while (True) — 왜 차이점이 있습니까 (python 2 바이트 코드에서)?

perl의 무한 루프에 대한이 질문에 흥미가 있습니다. while (1) Vs. for (;;) 속도 차이가 있습니까? , 나는 파이썬에서 비슷한 비교를 실행하기로 결정했습니다. 컴파일러가 while(True): passwhile(1): pass에 대해 동일한 바이트 코드를 생성 할 것으로 예상 했지만 실제로 python2.7에서는 그렇지 않습니다.

다음 스크립트 :

import dis

def while_one():
    while 1:
        pass

def while_true():
    while True:
        pass

print("while 1")
print("----------------------------")
dis.dis(while_one)

print("while True")
print("----------------------------")
dis.dis(while_true)

다음 결과를 생성합니다.

while 1
----------------------------
  4           0 SETUP_LOOP               3 (to 6)

  5     >>    3 JUMP_ABSOLUTE            3
        >>    6 LOAD_CONST               0 (None)
              9 RETURN_VALUE
while True
----------------------------
  8           0 SETUP_LOOP              12 (to 15)
        >>    3 LOAD_GLOBAL              0 (True)
              6 JUMP_IF_FALSE            4 (to 13)
              9 POP_TOP

  9          10 JUMP_ABSOLUTE            3
        >>   13 POP_TOP
             14 POP_BLOCK
        >>   15 LOAD_CONST               0 (None)
             18 RETURN_VALUE        

사용 while True은 눈에 띄게 더 복잡합니다. 왜 이런거야?

다른 컨텍스트에서 파이썬 True은 1 과 같은 것처럼 작동합니다 .

>>> True == 1
True

>>> True + True
2

while두 가지를 구별하는 이유는 무엇 입니까?

python3이 동일한 작업을 사용하여 문을 평가한다는 것을 알았습니다.

while 1
----------------------------
  4           0 SETUP_LOOP               3 (to 6)

  5     >>    3 JUMP_ABSOLUTE            3
        >>    6 LOAD_CONST               0 (None)
              9 RETURN_VALUE
while True
----------------------------
  8           0 SETUP_LOOP               3 (to 6)

  9     >>    3 JUMP_ABSOLUTE            3
        >>    6 LOAD_CONST               0 (None)
              9 RETURN_VALUE         

부울이 평가되는 방식에 python3이 변경 되었습니까?



답변

Python 2.x에서는 True키워드가 아니라 유형 에서 1로 정의 된 내장 전역 상수 일뿐 bool입니다. 따라서 인터프리터는 여전히의 내용을로드해야합니다 True. 즉, True재 할당 가능합니다.

Python 2.7 (r27:82508, Jul  3 2010, 21:12:11)
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> True = 4
>>> True
4

Python 3.x 에서는 진정으로 키워드 이자 실제 상수가됩니다.

Python 3.1.2 (r312:79147, Jul 19 2010, 21:03:37)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> True = 4
  File "<stdin>", line 1
SyntaxError: assignment to keyword

따라서 인터프리터는 while True:루프를 무한 루프로 대체 할 수 있습니다 .


답변

이것은 옳지 않습니다.

따라서 인터프리터는 while True : 루프를 무한 루프로 대체 할 수 있습니다.

여전히 루프에서 벗어날 수 있습니다. 그러나 그러한 루프의 else절은 Python 3에서 절대 액세스되지 않는다는 것은 사실입니다. 또한 값 조회를 단순화하면 다음과 같이 빠르게 실행됩니다.while 1 Python 2 .

성능 비교

다소 사소하지 않은 while 루프의 시간 차이를 보여줍니다.

설정

def while1():
    x = 0
    while 1:
        x += 1
        if x == 10:
            break

def whileTrue():
    x = 0
    while True:
        x += 1
        if x == 10:
            break

파이썬 2

>>> import timeit
>>> min(timeit.repeat(while1))
0.49712109565734863
>>> min(timeit.repeat(whileTrue))
0.756627082824707

파이썬 3

>>> import timeit
>>> min(timeit.repeat(while1))
0.6462970309949014
>>> min(timeit.repeat(whileTrue))
0.6450748789939098

설명

차이점을 설명하기 위해 Python 2에서

>>> import keyword
>>> 'True' in keyword.kwlist
False

하지만 파이썬 3에서는

>>> import keyword
>>> 'True' in keyword.kwlist
True
>>> True = 'true?'
  File "<stdin>", line 1
SyntaxError: can't assign to keyword

TruePython 3의 키워드 이므로 인터프리터는 누군가가 다른 값으로 대체했는지 확인하기 위해 값을 찾을 필요가 없습니다. 그러나 True다른 값에 할당 할 수 있기 때문에 통역사는 매번 그것을 찾아야합니다.

Python 2에 대한 결론

파이썬 2에 꽉, 장기 실행 루프가있는 경우, 당신은 아마 사용해야합니다 while 1:대신 while True:.

Python 3에 대한 결론

while True:루프를 벗어날 조건이없는 경우 사용하십시오 .


답변

이것은 이미 훌륭한 답변을 가지고있는 7 년 된 질문이지만, 어떤 답변에서도 다루지 않은 질문에 대한 오해로 인해 중복으로 표시된 다른 질문 중 일부에 대해 잠재적으로 혼란 스러울 수 있습니다.

다른 컨텍스트에서 python은 True가 1 인 것처럼 작동합니다.

>>> True == 1
True

>>> True + True
2

while은 왜 둘을 구별합니까?

사실, while여기서는 전혀 다른 일을하지 않습니다. 그것은 구별 1하고 True것을 정확히 같은 방법으로 +예 않습니다.


2.7 :

>>> dis.dis('True == 1')
  1           0 LOAD_GLOBAL              0 (True)
              3 LOAD_CONST               1 (1)
              6 COMPARE_OP               2 (==)
              9 RETURN_VALUE

>>> dis.dis('True == 1')
  1           0 LOAD_GLOBAL              0 (True)
              3 LOAD_GLOBAL              0 (True)
              6 BINARY_ADD
              9 RETURN_VALUE

이제 비교 :

>>> dis.dis('1 + 1')
  1           0 LOAD_CONST               1 (2)
              3 RETURN_VALUE

LOAD_GLOBAL (True)for each를 방출 True하고 옵티마이 저가 전역으로 할 수있는 일은 없습니다. 그래서, while구별하는 1True동일한 이유로 +않습니다. (그리고 ==옵티마이 저가 비교를 최적화하지 않기 때문에 구별하지 않습니다.)


이제 3.6을 비교하십시오.

>>> dis.dis('True == 1')
  1           0 LOAD_CONST               0 (True)
              2 LOAD_CONST               1 (1)
              4 COMPARE_OP               2 (==)
              6 RETURN_VALUE

>>> dis.dis('True + True')
  1           0 LOAD_CONST               1 (2)
              2 RETURN_VALUE

여기서는 LOAD_CONST (True)최적화 프로그램 이 활용할 있는 키워드에 대한를 내 보냅니다 . 그래서 True + 1 하지 않습니다 정확히 같은 이유를 들어 구분 while True하지 않습니다. ( ==최적화 프로그램이 비교를 최적화하지 않기 때문에 여전히 구별하지 않습니다.)


코드가 밖으로 최적화되어 있지 않은 경우 한편, 인터프리터는 치료 끝 True1이러한 경우의 세에서 정확히 같은. bool(A)의 서브 클래스 int및 상속에서 그 방법의 대부분은 int, 그리고True 당신이 일을하고 있는지, 1. 지금의 내부 정수 값을 가지고 while테스트를 ( __bool__3.x의에서, __nonzero__(2.X에서) 비교 __eq__), 또는 산술 ( __add__), True또는 을 사용하든 동일한 메서드를 호출합니다 1.


답변