PEP 378 – 천 단위 구분자를 위한 형식 지정자
- Author:
- Raymond Hettinger <python at rcn.com>
- Status:
- Final
- Type:
- Standards Track
- Created:
- 12-Mar-2009
- Python-Version:
- 2.7, 3.1
- Post-History:
- 12-Mar-2009
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
동기
로케일에 의존하지 않고 천 단위 구분자로 숫자를 형식화하는 간단한 방법을 제공합니다.
천 단위 구분자를 추가하는 것은 프로그램의 출력을 사람이 읽기 쉽게 만드는 가장 간단한 방법 중 하나이며, 출력을 더 전문적으로 보이게 하고 가독성을 높여 줍니다.
금융 분야에서는 천 단위 구분자가 들어간 출력이 표준입니다. 금융 사용자와 비전문 프로그래머는 로케일 방식이 번거롭고 난해하며 직관적이지 않다고 느낍니다.
locale 모듈에는 두 가지 다른 문제가 있습니다. 첫째, 로케일은 전역 설정이므로 여러 로케일로 요청을 처리해야 하는 멀티스레드 애플리케이션에는 적합하지 않습니다. 둘째, 해당 로케일의 이름(예: “de_DE”)은 플랫폼마다 다를 수 있으며 아예 정의되어 있지 않을 수도 있습니다. 로케일 모듈 문서에서는 이런 문제와 many other challenges를 자세히 설명합니다.
로케일 모듈을 대체하거나, 국제화 작업을 수행하거나, 가능한 모든 관례를 수용하는 것은 목표가 아닙니다. 그러한 작업에는 Babel 같은 강력한 도구가 더 적합합니다. 대신 많은 사용자가 흔히 하는 일상적인 작업을 더 쉽게 만드는 것이 목표입니다.
주요 제안(Alyssa Coghlan 제안, 원래 명칭은 제안 I)
format() 지정자 미니 언어에 쉼표가 추가됩니다.:
[[fill]align][sign][#][0][width][,][.precision][type]
‘,’ 옵션은 출력에 천 단위 구분자로 쉼표를 포함해야 함을 나타냅니다. 마침표를 소수점으로 사용하지 않는 로케일과 마찬가지로, 자릿수 구분에 다른 관례를 사용하는 로케일에서는 적절한 형식을 얻으려면 locale 모듈을 사용해야 합니다.
이 제안은 float, int, decimal 모두에서 잘 동작합니다. 또한 다른 구분자로 쉽게 대체할 수 있습니다. 예를 들면 다음과 같습니다.:
format(n, "6,d").replace(",", "_")
이 기법은 완전히 범용적이지만, 쉼표와 마침표를 서로 바꿔야 하는 한 가지 경우에는 불편합니다.:
format(n, "6,f").replace(",", "X").replace(".", ",").replace("X", ".")
width 인자는 쉼표와 소수점을 포함한 전체 길이를 뜻합니다.:
format(1234, "08,d") --> '0001,234'
format(1234.5, "08,.1f") --> '01,234.5'
‘,’ 옵션은 ‘d’, ‘e’, ‘f’, ‘g’, ‘E’, ‘G’, ‘%’, ‘F’, ‘’ 타입에 대해 위와 같이 정의됩니다. 향후 확장을 허용하기 위해 이진수, 8진수, 16진수, 문자 등 다른 타입에 대해서는 정의하지 않습니다.
이 제안은 대안 제안보다 간단하다는 장점이 있지만, 유연성이 훨씬 떨어지고 별도 작업 없이 바로 요구 사항을 충족할 수 있는 사용자도 더 적습니다. 다른 구분자를 지정하기 위한 별도의 해결책이 나올 것으로 예상됩니다.
미니 언어의 현재 버전
- Python 2.6 docs
- PEP 3101 고급 문자열 형식화
다른 언어의 방식 조사
웹을 조사해 보니, 천 단위 구분자는 대개 쉼표(COMMA), 마침표(DOT), 공백(SPACE), 아포스트로피(APOSTROPHE), 밑줄(UNDERSCORE) 중 하나였습니다.
C-Sharp은 두 가지 방식(픽처 포매팅과 타입 지정자)을 모두 제공합니다. 타입 지정자 방식은 로케일을 인식합니다. 픽처 포매팅은 천 단위 구분자로 COMMA만 제공합니다:
String.Format("{0:n}", 12400) ==> "12,400"
String.Format("{0:0,0}", 12400) ==> "12,400"
Common Lisp은 ~D 십진 타입 지정자 앞에 COLON을 붙여 천 단위 구분자로 COMMA를 출력합니다. ~D의 일반 형식은 ~mincol,padchar,commachar,commaintervalD입니다. padchar의 기본값은 SPACE입니다. commachar의 기본값은 COMMA입니다. commainterval의 기본값은 3입니다.
(format nil "~:D" 229345007) => "229,345,007"
- ADA language는 숫자 리터럴에 밑줄을 허용합니다.
Visual Basic과 그 계열 언어들(MS Excel 등)은 완전히 다른 방식을 사용하며, 다음과 같은 매우 유연한 사용자 정의 형식 지정자를 제공합니다:
"_($* #,##0_)".
COBOL은 다음과 같은 픽처 절을 사용합니다:
PICTURE $***,**9.99CR
Java는 "#,##0.00;(#,##0.00)"와 같은 픽처 패턴(양수용 패턴 하나와 선택적인 음수용 패턴 하나)을 사용하는 Decimal.Format Class를 제공합니다. 이 클래스는 백 단위와 만 단위를 포함한 임의의 그룹화와 불균등한 그룹화를 허용합니다. 특수 패턴 문자는 지역화되지 않습니다(소수 구분자로 DOT를, 그룹 구분자로 COMMA를 사용합니다). 사용자는 포매터의 DecimalFormatSymbols 객체를 사용하여 대체 기호 집합을 제공할 수 있습니다.
대안 제안(Eric Smith가 제안했으며, 원래 이름은 Proposal II)
천 단위 구분자와 소수 구분자를 모두 사용자가 지정할 수 있게 하되, 로케일은 인식하지 않도록 합니다. 단순성을 위해 선택지를 쉼표(COMMA), 마침표(DOT), 공백(SPACE), 아포스트로피(APOSTROPHE), 밑줄(UNDERSCORE)로 제한합니다. SPACE는 U+0020 또는 U+00A0 중 하나일 수 있습니다.
구분자 뒤에 정밀도가 오면 그 구분자는 소수 구분자이며, 그 앞에 선택적으로 오는 구분자는 천 단위 구분자입니다. 정밀도가 없으면 단독으로 쓰인 지정자는 천 단위 구분자를 의미합니다:
[[fill]align][sign][#][0][width][tsep][dsep precision][type]
예시:
format(1234, "8.1f") --> ' 1234.0'
format(1234, "8,1f") --> ' 1234,0'
format(1234, "8.,1f") --> ' 1.234,0'
format(1234, "8 ,f") --> ' 1 234,0'
format(1234, "8d") --> ' 1234'
format(1234, "8,d") --> ' 1,234'
format(1234, "8_d") --> ' 1_234'
이 제안은 대부분의 요구를 충족하지만, 그 대가로 파싱에 약간 더 많은 노력이 듭니다. 가능한 모든 관례를 다루지는 않지만, 선택지 중 적어도 하나(공백 또는 밑줄)는 다양한 배경을 지닌 많은 사람들이 읽고 이해할 수 있으며 유용하게 쓸 수 있을 것입니다.
예에서 볼 수 있듯이, width 인자는 천 단위 구분자와 소수 구분자를 포함한 전체 길이를 의미합니다.
로케일 모듈에 대한 변경은 제안하지 않습니다.
천 단위 구분자는 ‘d’, ‘e’, ‘f’, ‘g’, ‘%’, ‘E’, ‘G’, ‘F’ 타입에 대해 위와 같이 정의됩니다. 향후 확장을 허용하기 위해 그 밖의 타입(2진수, 8진수, 16진수, 문자 등)에 대해서는 정의하지 않습니다.
이 대안 제안의 단점은 단일 구분자가 천 단위 구분자인지 소수 구분자인지를 머릿속으로 파싱하기 어렵다는 점입니다. 소수 구분자를 정밀도 지정자와 연결하는 것은 어쩌면 지나치게 난해할지도 모릅니다.
논평
- 일부 의견 제시자는 형식 문자열이라는 발상 자체를 좋아하지 않으며, 형식 문자열이 읽기 어렵다고 생각합니다. 제안된 대안으로는 COBOL 스타일의 PICTURE 방식이나, 가능한 모든 조합에 대해 키워드 인자를 받는 편의 함수 등이 있습니다.
- 일부 뉴스그룹 응답자는 국제화되지 않은 스크립트가 설 자리는 없으며, 특정 선택을 하드코딩하는 간단한 방법을 제공하는 것은 (로케일을 고려하는 접근 방식을 사용할 동기를 줄이므로) 퇴보라고 생각합니다.
- 또 다른 의견은 개별 형식 문자열에 특정 관례를 넣어 두면 나중에 그 관례를 바꾸기 어려워진다는 것입니다. 실행 가능한 대안이 제시되지는 않았지만, 대체적인 생각은 관례를 한 번 설정하면 모든 곳에 적용되도록 하자는 것입니다(다른 사람들은 로케일이 이미 그런 방법을 제공한다고 지적했습니다).
- 부동 소수점 수의 소수부에서 자릿수를 묶는 선례가 일부 있지만, 이 PEP는 그 영역까지 다루지 않습니다. 소수점 왼쪽의 자릿수만 묶습니다. 이것이 향후 확장을 배제하는 것은 아닙니다. 단지 서식 언어에 대해 일반적으로 유용한 단일 확장에 집중할 뿐입니다.
- James Knight는 인도/파키스탄의 숫자 체계가 백 단위로 묶는다는 점을 언급했습니다. Ben Finney는 중국에서는 만 단위로 묶는다는 점을 언급했습니다. Eric Smith는 이런 방식이 이미 로케일 모듈의 “n” 지정자로 처리된다고 지적했습니다(정수에 한해서이기는 합니다). 이 PEP는 이러한 모든 가능성을 지원하려고 하지 않습니다. 이 PEP는 많은(모든 상황은 아니지만) 상황에서 가독성을 빠르게 향상시킬 수 있는, 비교적 흔한 단일 그룹화 관례에 집중합니다.
Copyright
This document has been placed in the public domain.