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-literal은 f-string과 완전히 하위 호환되며, 합법으로 간주되는 문법을 확장합니다.
참조 구현
추후 결정
참고 자료
Copyright
This document has been placed in the public domain.