[python] 파이썬 3은 왜 “00”을 0의 리터럴로 허용하지만 “01”을 1의 리터럴로 허용하지 않습니까?

왜 파이썬 3은 “00”을 0에 대한 리터럴로 허용하지만 “01”을 1에 대한 리터럴로 허용하지 않습니까? 타당한 이유가 있습니까? 이 불일치는 나를 당황하게합니다. (그리고 일관성과 같은 목표를 달성하기 위해 의도적으로 이전 버전과의 호환성을 깨뜨린 Python 3에 대해 이야기하고 있습니다.)

예를 들면 :

>>> from datetime import time
>>> time(16, 00)
datetime.time(16, 0)
>>> time(16, 01)
  File "<stdin>", line 1
    time(16, 01)
              ^
SyntaxError: invalid token
>>>



답변

https://docs.python.org/3/reference/lexical_analysis.html#integer-literals :

정수 리터럴은 다음 어휘 정의로 설명됩니다.

integer        ::=  decimalinteger | octinteger | hexinteger | bininteger
decimalinteger ::=  nonzerodigit digit* | "0"+
nonzerodigit   ::=  "1"..."9"
digit          ::=  "0"..."9"
octinteger     ::=  "0" ("o" | "O") octdigit+
hexinteger     ::=  "0" ("x" | "X") hexdigit+
bininteger     ::=  "0" ("b" | "B") bindigit+
octdigit       ::=  "0"..."7"
hexdigit       ::=  digit | "a"..."f" | "A"..."F"
bindigit       ::=  "0" | "1"

사용 가능한 메모리에 저장할 수있는 것 외에는 정수 리터럴의 길이에 대한 제한이 없습니다.

0이 아닌 10 진수의 선행 0은 허용되지 않습니다. 이것은 파이썬이 3.0 이전에 사용했던 C 스타일 8 진 리터럴과의 명확성을위한 것입니다.

여기에서 언급했듯이 0이 아닌 10 진수의 선행 0은 허용되지 않습니다. 파이썬 2에는 없었던"0"+ 매우 특별한 경우로 합법적입니다 .

integer        ::=  decimalinteger | octinteger | hexinteger | bininteger
decimalinteger ::=  nonzerodigit digit* | "0"
octinteger     ::=  "0" ("o" | "O") octdigit+ | "0" octdigit+

SVN commit r55866 은 tokenizer에서 PEP 3127을 구현하여 이전 0<octal>번호 를 금지합니다 . 그러나 흥미롭게도 다음과 같은 메모도 추가합니다.

/* in any case, allow '0' as a literal */

다음 숫자 시퀀스에 0이 아닌 숫자가 포함 된 경우 nonzero에만 a를 던지는 특수 플래그가 SyntaxError있습니다.

PEP 3127 이이 경우를 허용하지 않기 때문에 이것은 이상합니다 .

이 PEP는 선행 0을 사용하여 8 진수를 지정하는 기능이 Python 3.0 (및 Python 3.0 미리보기 모드 2.6)의 언어에서 제거되고 선행 “0”이 올 때마다 SyntaxError가 발생한다고 제안합니다. 바로 뒤에 다른 숫자가옵니다 .

(강조 내)

따라서 여러 개의 0이 허용된다는 사실은 기술적 으로 PEP를 위반하는 것이며 기본적으로 Georg Brandl에 의해 특수 사례로 구현되었습니다. 그는 해당 문서를 변경하여 (이전에는에서 다루었던) "0"+유효한 사례 임을 기록했습니다 .decimalintegeroctinteger

우리는 Georg가 왜 유효화를 선택 했는지 정확히 알지 못할 것입니다 "0"+. 파이썬에서 영원히 이상한 경우로 남아있을 수 있습니다.


업데이트 [2015 년 7 월 28 일] :이 질문은 Georg가 다음 같이 했던 파이썬 아이디어에 대한 활발한 토론 스레드로 이어졌습니다 .

Steven D’ Aprano는 다음과 같이 썼습니다.

왜 그렇게 정의 되었습니까? […] 왜 우리는 0을 얻기 위해 0000을 쓰겠습니까?

말해 줄 수는 있지만 그럼 죽여야 해요

게오르그

나중에 스레드 는이 특별한 경우를 제거하기 위해이 버그 보고서를 생성 했습니다 . 여기 Georg는 다음과 같이 말합니다 .

이 의도적 인 변경의 이유를 기억하지 못합니다 (문서 변경에서 볼 수 있음).

나는 지금이 변화에 대한 좋은 이유를 생각 해낼 수 없다 …]

따라서 우리는 그것을 가지고 있습니다.이 불일치의 정확한 이유는 시간이 지남에 따라 사라집니다.

마지막으로, 버그 보고서가 거부되었습니다. 나머지 Python 3.x에서는 0 정수에서만 선행 0이 계속 허용됩니다.


답변

특별한 경우 ( "0"+)

2.4.4. 정수 리터럴

정수 리터럴은 다음 어휘 정의로 설명됩니다.

정수 :: = decimalinteger | 옥틴 테거 | hexinteger | 비정 수
decimalinteger :: = 0이 아닌 숫자 * | "0"+
0이 아닌 숫자 :: = "1"... "9"
숫자 :: = "0"... "9"
8 진수 :: = "0"( "o"| "O") 8 진수 +
hexinteger :: = "0"( "x"| "X") 16 진수 +
bininteger :: = "0"( "b"| "B") bindigit +
8 진수 :: = "0"... "7"
16 진수 :: = 숫자 | "a"... "f"| "A"... "F"
bindigit :: = "0"| "1"

문법을 살펴보면 0특별한 경우 가 필요 하다는 것을 쉽게 알 수 있습니다 . 그래도 ‘ +‘가 왜 필요한지 잘 모르겠습니다 . 개발 메일 링리스트를 살펴볼 시간입니다 …


Python2에서, 둘 이상의 것을주의하는 것이 재미 0int로서 구문 분석 octinteger(최종 결과는 여전히 0하지만)

decimalinteger :: = 0이 아닌 숫자 * | "0"
8 진수 :: = "0"( "o"| "O") 8 진수 + | "0"8 진수 +


답변

Python2는 선행 0을 사용하여 8 진수를 지정했습니다.

>>> 010
8

이 (? 오해의 소지가) 문제를 방지하려면, Python3 명시 적 접두사를 요구한다 0b, 0o, 0x:

>>> 0o10
8


답변