PEP 536 – 리터럴 문자열 보간을 위한 최종 문법
- Author:
- Philipp Angerer <phil.angerer at gmail.com>
- Status:
- Withdrawn
- Type:
- Standards Track
- Created:
- 11-Dec-2016
- Python-Version:
- 3.7
- Post-History:
- 18-Aug-2016, 23-Dec-2016, 15-Mar-2019
- Resolution:
- Discourse message
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
PEP 498은 리터럴 문자열 보간(또는 “f-문자열”)을 도입했습니다. 그러나 이러한 리터럴의 표현식 부분에는 몇 가지 제약이 있습니다. 이 PEP는 이러한 제약을 없애는 형식 문법을 제안하며, “f-문자열”을 “f 표현식”, 즉 f-리터럴로 격상합니다.
이 PEP는 PEP 498에서 도입된 f-문자열을 확장하므로, 이 문서를 읽으려면 PEP 498을 알고 있어야 합니다.
PEP 철회
이 PEP는 PEP 701로 대체되어 철회되었습니다. PEP 701은 이 PEP의 중요한 사항을 모두 다룹니다.
용어
이 문서에서는 기존 문법을 “f-문자열”이라고 하고, 제안하는 문법을 “f-리터럴”이라고 합니다.
또한 f-리터럴/f-문자열 안에서 {}로 구분된 표현식을 “표현식 부분”이라고 하고, 그 주변의 정적인 문자열 내용을 “문자열 부분”이라고 합니다.
동기
현재 CPython의 f-문자열 구현은 기존의 문자열 파싱 장치와 그 토큰의 후처리에 의존합니다. 이 때문에 f-문자열 안에서 사용할 수 있는 표현식에 다음과 같은 몇 가지 제약이 생깁니다:
- 표현식 부분 안에서는 f-문자열을 구분하는 따옴표 문자를 사용할 수 없습니다:
>>> f'Magic wand: { bag['wand'] }' ^ SyntaxError: invalid syntax
- 이전에 검토되었던 우회 방법은 실행되는 코드 안에 이스케이프 시퀀스가 들어가게 하므로 f-문자열에서 금지되어 있습니다:
>>> f'Magic wand { bag[\'wand\'] } string' SyntaxError: f-string expression portion cannot include a backslash - 여러 줄 f-문자열에서도 주석이 금지되어 있습니다:
>>> f'''A complex trick: { ... bag['bag'] # recursive bags! ... }''' SyntaxError: f-string expression part cannot include '#' - 표현식 부분에서는
':'과'!'를 중괄호로 감싸야 합니다:>>> f'Useless use of lambdas: { lambda x: x*2 }' SyntaxError: unexpected EOF while parsing
이러한 제약은 언어 사용자 관점에서 아무런 쓸모가 없으며, f-리터럴에 예외 없는 정규 문법을 부여하고 이를 전용 파싱 코드로 구현하면 없앨 수 있습니다.
근거
Motivation에서 언급한 제약은 사용자가 f-리터럴의 구현 세부 사항을 잘 알지 못하는 한 명확하지 않고 직관에 어긋납니다.
앞서 언급했듯이, PEP 498의 이전 버전은 f-문자열의 어디에서나 이스케이프 시퀀스를 허용했으며, 여기에는 표현식 부분을 구분하는 중괄호를 인코딩하는 데 사용하는 경우와 표현식 부분의 코드 안에서 사용하는 경우도 포함되었습니다. 이스케이프 시퀀스는 코드가 파싱되기 전에 확장되었을 것이며, 이는 다음과 같은 몇 가지 중요한 영향을 미쳤을 것입니다:
#. 사람이 읽을 때 어느 부분이 표현식이고 어느 부분이 문자열인지 분명하지 않을 것입니다. “난독화/음흉한 Python 챌린지”에 쓰기 좋은 소재입니다 #. 구문 강조기는 중첩된 문법을 파싱하는 데는 능숙하지만, 이스케이프 시퀀스를 인식하는 데는 그렇지 않습니다. ECMAScript 2016(JavaScript)은 식별자에 이스케이프 시퀀스를 허용하지만 [1], 저자는 이를 활용하는 코드를 올바르게 강조 표시할 수 있는 문법 강조기를 알지 못합니다.
그 결과, 문법 강조의 도움이 있든 없든 표현식 부분을 알아보기가 더 어려워질 것입니다. 새 문법을 사용하면 f-리터럴을 올바르게 파싱하고 표시하도록 구문 강조기를 쉽게 확장할 수 있습니다:
f'Magic wand: {bag['wand']:^10}'
이스케이프 시퀀스가 포함될 수 있는 표현식 부분을 하이라이트하려면 키워드, 구분자 및 기타 모든 언어 구문에 이스케이프 시퀀스가 나타날 가능성을 고려하여 전체 표현식 문법의 모든 규칙을 수정한 사본을 만들어야 합니다. 이렇게 한 번 복제하면 이스케이프 깊이가 한 단계만 생기므로, 재귀적인 f-리터럴에서 더 깊은 이스케이프를 처리하려면 복제를 반복해야 합니다. 저자가 아는 하이라이트 엔진 중에는 특정 컨텍스트에 규칙을 적용하기 전에 이스케이프 시퀀스를 확장하는 기능을 지원하는 것이 없기 때문입니다. 반면 컨텍스트 중첩은 모든 하이라이트 엔진의 표준 기능입니다.
익숙함도 한몫합니다. 변수 이름만이 아니라 표현식을 사용하는 문자열 보간 방식을 채택한 다른 모든 언어에서는 이스케이프 시퀀스를 확장하지 않고도 표현식을 임의로 중첩할 수 있습니다. [2]
명세
PEP 498은 f-문자열을 다음과 같이 명세했지만, 여기에 제약을 둡니다:
f ' <text> { <expression> <optional !s, !r, or !a> <optional : format specifier> } <text> ... '
아래에서 설명하는 것처럼, PEP에서 언급한 모든 제약이 f-리터럴에서는 해제됩니다:
- 이제 표현식 부분에 f-리터럴을 구분하는 데 사용된 것과 같은 종류의 따옴표로 구분된 문자열을 넣을 수 있습니다.
- 이제 Python 코드의 다른 모든 곳과 마찬가지로 표현식 안에도 백슬래시가 올 수 있습니다. f-리터럴 안에 중첩된 문자열의 경우, 가장 안쪽 문자열이 평가될 때 이스케이프 시퀀스가 확장됩니다.
'#'문자를 사용하는 주석은 여러 줄 f-리터럴에서만 사용할 수 있습니다. 주석은 줄 끝에서 끝나기 때문입니다(그래서 한 줄 f-리터럴은 닫을 수 없게 됩니다).- 표현식 부분은 문법적으로 유효한 곳이라면 어디에나
':'또는'!'를 포함할 수 있습니다. 표현식의 일부가 아닌 첫 번째':'또는'!'뒤에는 유효한 강제 변환이나 형식 지정자가 와야 합니다.
PEP 498에서 명시적으로 언급하지 않았지만 남아 있는 제약은 표현식 부분에서의 줄 바꿈입니다. 단일 ' 또는 " 문자로 구분된 문자열은 한 줄로 이루어질 것으로 기대되므로, 한 줄 문자열의 표현식 부분에서는 줄 바꿈이 여전히 허용되지 않습니다.
Note
제약을 해제하는 것으로 충분합니까, 아니면 더 완전한 문법을 명시해야 합니까?
하위 호환성
f-리터럴은 f-문자열과 완전히 하위 호환되며, 합법적인 것으로 간주되는 문법을 확장합니다.
참조 구현
미정
참고 문헌
Copyright
This document has been placed in the public domain.