PEP 515 – 숫자 리터럴의 밑줄
- Author:
- Georg Brandl, Serhiy Storchaka
- Status:
- Final
- Type:
- Standards Track
- Created:
- 10-Feb-2016
- Python-Version:
- 3.6
- Post-History:
- 10-Feb-2016, 11-Feb-2016
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록 및 근거
이 PEP는 정수, 부동 소수점, 복소수 리터럴에서 밑줄을 자릿수 그룹화용 시각적 구분자로 쓸 수 있도록 Python의 문법과 문자열에서 숫자를 만드는 생성자를 확장하자고 제안합니다.
이는 다른 현대 언어에서 흔히 볼 수 있는 기능이며, 긴 리터럴이나 16진수 표기법의 바이트나 워드처럼 값이 여러 부분으로 명확하게 나뉘어야 하는 리터럴의 가독성을 높이는 데 도움이 될 수 있습니다.
예시:
# grouping decimal numbers by thousands
amount = 10_000_000.0
# grouping hexadecimal addresses by words
addr = 0xCAFE_F00D
# grouping bits into nibbles in a binary literal
flags = 0b_0011_1111_0100_1110
# same, for string conversions
flags = int('0b_1111_0000', 2)
명세
현재 제안은 숫자 리터럴에서 숫자 사이와 진법 지정자 뒤에 밑줄 하나를 허용하는 것입니다. 밑줄은 의미상 아무런 뜻이 없으며, 리터럴은 밑줄이 없는 것처럼 구문 분석됩니다.
리터럴 문법
따라서 정수 리터럴의 생성 규칙 목록은 다음과 같습니다.:
integer: decinteger | bininteger | octinteger | hexinteger
decinteger: nonzerodigit (["_"] digit)* | "0" (["_"] "0")*
bininteger: "0" ("b" | "B") (["_"] bindigit)+
octinteger: "0" ("o" | "O") (["_"] octdigit)+
hexinteger: "0" ("x" | "X") (["_"] hexdigit)+
nonzerodigit: "1"..."9"
digit: "0"..."9"
bindigit: "0" | "1"
octdigit: "0"..."7"
hexdigit: digit | "a"..."f" | "A"..."F"
부동 소수점 및 복소수 리터럴의 경우:
floatnumber: pointfloat | exponentfloat
pointfloat: [digitpart] fraction | digitpart "."
exponentfloat: (digitpart | pointfloat) exponent
digitpart: digit (["_"] digit)*
fraction: "." digitpart
exponent: ("e" | "E") ["+" | "-"] digitpart
imagnumber: (floatnumber | digitpart) ("j" | "J")
생성자
배치에 관한 같은 규칙에 따라, 다음 생성자에서도 밑줄을 쓸 수 있습니다:
int()(모든 진법)float()complex()Decimal()
추가 변경 사항
새로운 스타일의 숫자-문자열 포매팅 언어를 확장해 천 단위 구분자로 _도 쓸 수 있게 합니다. 현재는 ,만 지원됩니다. 이를 이용하면 더 읽기 쉬운 리터럴이 들어간 코드를 쉽게 생성할 수 있습니다. [11]
문법은 쉼표와 같습니다. 예를 들어 너비가 10이고 구분자가 _이면 {:10_}로 씁니다.
b, x, o 형식 지정자에서도 _를 쓸 수 있으며, 이때는 4자리씩 묶습니다.
선행 사례
밑줄 그룹화를 허용하는 언어들은 밑줄을 둘 수 있는 위치에 대해 매우 다양한 규칙을 구현합니다. 언어 명세가 실제 동작과 다른 경우에는 실제 동작을 적었습니다. (“단일”과 “다중”은 밑줄을 여러 개 연달아 쓸 수 있는지를 나타냅니다.)
- Ada: 단일, 숫자 사이에서만 [8]
- C# (7.0용 공개 제안): 다중, 숫자 사이에서만 [6]
- C++14: 단일, 숫자 사이 (다른 구분자 채택) [1]
- D: 다중, 끝을 포함한 모든 위치 [2]
- Java: 다중, 숫자 사이에서만 [7]
- Julia: 단일, 숫자 사이에서만 (단, 부동 소수점 지수 부분에서는 불가) [9]
- Perl 5: 다중, 사실상 모든 위치 (문서에는 숫자 사이에 밑줄 하나로 제한된다고 되어 있음) [3]
- Ruby: 한 개만, 숫자 사이에서만 허용합니다(문서에는 “어디에나”라고 되어 있습니다). [10]
- Rust: 여러 개를 어디에나 허용하지만, 지수 “e”와 숫자 사이는 예외입니다. [4]
- Swift: 여러 개를 숫자 사이와 끝에 허용합니다(설명 문구에는 “숫자 사이”에만 허용한다고 되어 있습니다). [5]
대안 문법
밑줄 배치 규칙
위에서 명시한 비교적 엄격한 규칙 대신, 밑줄 사용을 덜 제한할 수도 있습니다. 다른 언어에서 볼 수 있듯이, 흔히 쓰이는 규칙은 다음과 같습니다:
- 연속된 밑줄은 한 개만, 숫자 사이에서만 허용합니다.
- 연속된 밑줄을 여러 개 허용하지만, 숫자 사이에서만 허용합니다.
- 연속된 밑줄을 여러 개 허용하며, 리터럴의 시작이나 소수점 뒤와 같은 특수한 위치를 제외한 대부분의 위치에서 허용합니다.
이 PEP의 문법이 최종적으로 선택된 이유는 일반적인 사용 사례를 포괄하면서도, 어차피 스타일 가이드에서 사용을 권장하지 않아야 할 문법은 허용하지 않기 때문입니다.
덜 흔한 규칙으로는 N자리마다만 밑줄을 허용하는 방식이 있습니다(N은 10진 리터럴이면 3, 16진 리터럴이면 4일 수 있습니다). 이는 불필요하게 제한적이며, 특히 구분자 배치가 문화권마다 다르다는 점을 고려하면 더욱 그렇습니다.
다른 구분자
제안된 대안 문법 중 하나는 그룹 구분에 공백을 사용하는 것이었습니다. 인접한 리터럴을 결합하는 선례로 문자열이 있기는 하지만, 이 동작은 밑줄로는 일어날 수 없는 예기치 않은 결과를 낳을 수 있습니다. 또한 공백을 전반적으로 무시하는 언어를 제외하면, 이 규칙을 사용하는 다른 언어는 알려져 있지 않습니다.
C++14는 그룹화에 아포스트로피를 도입했지만(밑줄은 사용자 정의 리터럴과 모호성을 일으키기 때문입니다), Python에서는 문자열 리터럴에 아포스트로피를 사용하므로 이 방식은 고려하지 않습니다. [1]
구현
위에서 제시한 명세를 구현하는 예비 패치가 이슈 트래커에 게시되었습니다. [12]
참고 문헌
Copyright
This document has been placed in the public domain.