- 2. Lexical analysis
파이썬 프로그램은 파서에 의해 읽혀집니다. 구문 분석기에 대한 입력은 어휘 분석기에 의해 생성된 토큰 스트림입니다. 이 장에서는 어휘 분석기가 파일을 토큰으로 나누는 방법을 설명합니다.
Python은 프로그램 텍스트를 유니코드 코드 포인트로 읽습니다. 소스 파일의 인코딩은 인코딩 선언으로 지정할 수 있으며 기본값은 UTF-8입니다. 자세한 내용은 PEP 3120을 참조하십시오. 소스 파일을 디코딩할 수 없으면 SyntaxError가 발생합니다.
2.1. Line structure
Python 프로그램은 여러 논리적 라인으로 나뉩니다.
2.1.1. Logical lines
논리적 줄의 끝은 토큰 NEWLINE으로 표시됩니다. 명령문은 구문에서 NEWLINE이 허용되는 경우(예: 복합 명령문의 명령문 사이)를 제외하고 논리적 라인 경계를 넘을 수 없습니다. 논리 회선은 명시적 또는 암시적 회선 결합 규칙에 따라 하나 이상의 물리적 회선에서 구성됩니다.
2.1.2. Physical lines
물리적 줄은 줄 끝 순서로 끝나는 일련의 문자입니다. 소스 파일 및 문자열에서 표준 플랫폼 라인 종료 시퀀스를 사용할 수 있습니다. ASCII LF(줄 바꿈)를 사용하는 Unix 형식, ASCII 시퀀스 CR LF(리턴 다음에 줄 바꿈)를 사용하는 Windows 형식 또는 ASCII CR(리턴) 문자. 이 모든 양식은 플랫폼에 관계없이 동일하게 사용할 수 있습니다. 입력의 끝은 최종 물리적 라인에 대한 암시적 종결자 역할도 합니다.
Python을 포함할 때 줄 바꿈 문자에 대한 표준 C 규칙을 사용하여 소스 코드 문자열을 Python API에 전달해야 합니다(ASCII LF를 나타내는 \n 문자는 줄 종결자임).
2.1.3. Comments¶
주석은 문자열 리터럴의 일부가 아닌 해시 문자(#)로 시작하여 실제 행의 끝에서 끝납니다. 주석은 암시적 줄 결합 규칙이 호출되지 않는 한 논리 줄의 끝을 나타냅니다. 주석은 구문에서 무시됩니다.
2.1.4. Encoding declarations
Python 스크립트의 첫 번째 또는 두 번째 줄에 있는 주석이 정규식 coding[=:]\s*([-\w.]+)과 일치하면 이 주석은 인코딩 선언으로 처리됩니다. 이 식의 첫 번째 그룹은 소스 코드 파일의 인코딩 이름을 지정합니다. 인코딩 선언은 자체 줄에 나타나야 합니다. 두 번째 줄인 경우 첫 번째 줄도 주석 전용 줄이어야 합니다. 인코딩 표현식의 권장 형식은 다음과 같습니다.
# -*- coding: <encoding-name> -*-
GNU Emacs에서도 인정하는
# vim:fileencoding=<encoding-name>
Bram Moolenaar의 VIM에서 인정합니다.
인코딩 선언이 없으면 기본 인코딩은 UTF-8입니다. 또한 파일의 첫 번째 바이트가 UTF-8 바이트 순서 표시(b’\xef\xbb\xbf’)인 경우 선언된 파일 인코딩은 UTF-8입니다. ).
인코딩이 선언되면 인코딩 이름은 Python에서 인식되어야 합니다(표준 인코딩 참조). 인코딩은 문자열 리터럴, 주석 및 식별자를 포함한 모든 어휘 분석에 사용됩니다.
2.1.5. Explicit line joining
다음과 같이 백슬래시 문자()를 사용하여 두 개 이상의 물리적 라인을 논리적 라인으로 결합할 수 있습니다. 물리적 라인이 문자열 리터럴 또는 주석의 일부가 아닌 백슬래시로 끝나는 경우 단일 논리적 라인을 형성하는 다음과 결합됩니다. 백슬래시와 다음 줄 끝 문자를 삭제합니다. 예를 들어:
if 1900 < year < 2100 and 1 <= month <= 12 \
and 1 <= day <= 31 and 0 <= hour < 24 \
and 0 <= minute < 60 and 0 <= second < 60: # Looks like a valid date
return 1
백슬래시로 끝나는 줄에는 주석을 달 수 없습니다. 백슬래시는 주석을 계속하지 않습니다. 백슬래시는 문자열 리터럴을 제외하고는 토큰을 계속하지 않습니다. 백슬래시는 문자열 리터럴 외부 라인의 다른 곳에서는 불법입니다.
2.1.6. Implicit line joining
괄호, 대괄호 또는 중괄호 안의 표현식은 백슬래시를 사용하지 않고 둘 이상의 실제 행으로 분할될 수 있습니다. 예를 들어:
month_names = ['Januari', 'Februari', 'Maart', # These are the
'April', 'Mei', 'Juni', # Dutch names
'Juli', 'Augustus', 'September', # for the months
'Oktober', 'November', 'December'] # of the year
암시적으로 계속되는 줄은 주석을 포함할 수 있습니다. 이어지는 줄의 들여쓰기는 중요하지 않습니다. 빈 연속 줄이 허용됩니다. 암시적 연속 행 사이에는 NEWLINE 토큰이 없습니다. 암묵적으로 연속된 행은 삼중 따옴표 문자열 내에서도 발생할 수 있습니다(아래 참조). 이 경우 주석을 전달할 수 없습니다.
2.1.7. Blank lines
공백, 탭, 폼피드 및 가능하면 주석만 포함하는 논리 행은 무시됩니다(예: NEWLINE 토큰이 생성되지 않음). 문을 대화식으로 입력하는 동안 빈 줄 처리는 read-eval-print 루프의 구현에 따라 다를 수 있습니다. 표준 인터랙티브 인터프리터에서 완전히 비어 있는 논리적 줄(즉, 공백이나 주석도 포함하지 않는 줄)은 여러 줄 문을 종료합니다.
2.1.8. Indentation
논리적 줄의 시작 부분에 있는 선행 공백(공백 및 탭)은 줄의 들여쓰기 수준을 계산하는 데 사용되며, 차례로 명령문 그룹화를 결정하는 데 사용됩니다.
탭은 (왼쪽에서 오른쪽으로) 1에서 8개의 공백으로 대체되어 대체 문자까지 포함하여 총 문자 수가 8의 배수가 됩니다(이는 Unix에서 사용되는 것과 동일한 규칙입니다). 공백이 아닌 첫 번째 문자 앞의 총 공백 수는 줄의 들여쓰기를 결정합니다. 들여쓰기는 백슬래시를 사용하여 여러 줄로 나눌 수 없습니다. 첫 번째 백슬래시까지의 공백이 들여쓰기를 결정합니다.
공백에 있는 탭의 가치에 따라 의미가 달라지는 방식으로 소스 파일이 탭과 공백을 혼합하는 경우 들여쓰기가 일관성이 없는 것으로 거부됩니다. 이 경우 TabError가 발생합니다.
크로스 플랫폼 호환성 참고: 비 UNIX 플랫폼의 텍스트 편집기 특성 때문에 단일 소스 파일에서 들여쓰기에 공백과 탭을 혼합하여 사용하는 것은 현명하지 않습니다. 또한 플랫폼에 따라 최대 들여쓰기 수준을 명시적으로 제한할 수 있습니다.
줄의 시작 부분에 용지 공급 문자가 있을 수 있습니다. 위의 들여쓰기 계산에서는 무시됩니다. 선행 공백의 다른 위치에서 발생하는 용지 공급 문자는 정의되지 않은 영향을 미칩니다(예를 들어 공백 수를 0으로 재설정할 수 있음).
연속된 줄의 들여쓰기 수준은 다음과 같이 스택을 사용하여 INDENT 및 DEDENT 토큰을 생성하는 데 사용됩니다.
파일의 첫 번째 줄을 읽기 전에 단일 0이 스택에 푸시됩니다. 이것은 다시는 터지지 않을 것입니다. 스택에 푸시된 숫자는 항상 아래에서 위로 엄격하게 증가합니다. 각 논리 줄의 시작 부분에서 줄의 들여쓰기 수준을 스택의 맨 위 수준과 비교합니다. 같으면 아무 일도 일어나지 않습니다. 더 크면 스택에 푸시되고 하나의 INDENT 토큰이 생성됩니다. 더 작은 경우 스택에서 발생하는 숫자 중 하나여야 합니다. 더 큰 스택의 모든 숫자가 제거되고, 제거된 각 숫자에 대해 DEDENT 토큰이 생성됩니다. 파일 끝에서 0보다 큰 스택에 남아 있는 각 숫자에 대해 DEDENT 토큰이 생성됩니다.
다음은 올바르게(혼란스럽긴 하지만) 들여쓰기된 Python 코드의 예입니다.
def perm(l):
# Compute the list of all permutations of l
if len(l) <= 1:
return [l]
r = []
for i in range(len(l)):
s = l[:i] + l[i+1:]
p = perm(s)
for x in p:
r.append(l[i:i+1] + x)
return r
다음 예는 다양한 들여쓰기 오류를 보여줍니다.
def perm(l): # error: first line indented
for i in range(len(l)): # error: not indented
s = l[:i] + l[i+1:]
p = perm(l[:i] + l[i+1:]) # error: unexpected indent
for x in p:
r.append(l[i:i+1] + x)
return r # error: inconsistent dedent
(실제로 처음 세 개의 오류는 파서에 의해 감지됩니다. 마지막 오류만 어휘 분석기에 의해 발견됩니다. return r의 들여쓰기는 스택에서 팝된 수준과 일치하지 않습니다.)
2.1.9. Whitespace between tokens
논리적 줄의 시작 부분이나 문자열 리터럴을 제외하고 공백 문자 공백, 탭 및 양식 공급을 상호 교환하여 토큰을 구분할 수 있습니다. 두 토큰의 연결이 다른 토큰으로 해석될 수 있는 경우에만 두 토큰 사이에 공백이 필요합니다(예: ab는 하나의 토큰이지만 a b는 두 개의 토큰).
2.2. Other tokens
NEWLINE, INDENT 및 DEDENT 외에도 식별자, 키워드, 리터럴, 연산자 및 구분 기호와 같은 토큰 범주가 있습니다. 공백 문자(앞서 설명한 줄 종결자 제외)는 토큰이 아니지만 토큰을 구분하는 역할을 합니다. 모호성이 존재하는 경우 토큰은 왼쪽에서 오른쪽으로 읽을 때 합법적인 토큰을 형성하는 가능한 가장 긴 문자열로 구성됩니다.
2.3. Identifiers and keywords
식별자(이름이라고도 함)는 다음 어휘 정의로 설명됩니다.
Python의 식별자 구문은 유니코드 표준 부속서 UAX-31을 기반으로 하며 아래에 정의된 대로 정교화 및 변경됩니다. 자세한 내용은 PEP 3131도 참조하십시오.
ASCII 범위(U+0001..U+007F) 내에서 식별자에 유효한 문자는 Python 2.x에서와 동일합니다. 대문자와 소문자 A~Z, 밑줄 _ 및 첫 번째 문자를 제외하고 0에서 9까지의 숫자.
Python 3.0은 ASCII 범위 밖의 추가 문자를 도입합니다(PEP 3131 참조). 이러한 문자의 경우 분류에서는 unicodedata 모듈에 포함된 유니코드 문자 데이터베이스 버전을 사용합니다.
식별자는 길이에 제한이 없습니다. 대소문자가 중요합니다.
identifier ::= xid_start xid_continue*
id_start ::= <all characters in general categories Lu, Ll, Lt, Lm, Lo, Nl, the underscore, and characters with the Other_ID_Start property>
id_continue ::= <all characters in id_start, plus characters in the categories Mn, Mc, Nd, Pc and others with the Other_ID_Continue property>
xid_start ::= <all characters in id_start whose NFKC normalization is in "id_start xid_continue*">
xid_continue ::= <all characters in id_continue whose NFKC normalization is in "id_continue*">
위에서 언급한 유니코드 범주 코드는 다음을 나타냅니다.
- 루 – 대문자
- Ll – 소문자
- Lt – 제목 글자
- Lm – 수정자 문자
- Lo – 다른 문자
- Nl – 문자 숫자
- Mn – 비공백 표시
- Mc – 간격 결합 표시
- Nd – 십진수
- PC – 커넥터 구두점
- Other_ID_Start – 이전 버전과의 호환성을 지원하기 위한 PropList.txt의 명시적 문자 목록
- Other_ID_Continue – 마찬가지로
모든 식별자는 구문 분석하는 동안 일반 형식 NFKC로 변환됩니다. 식별자 비교는 NFKC를 기반으로 합니다.
유니코드 14.0.0에 대한 모든 유효한 식별자 문자를 나열하는 비표준 HTML 파일은 https://www.unicode.org/Public/14.0.0/ucd/DerivedCoreProperties.txt에서 찾을 수 있습니다.
2.3.1. Keywords
다음 식별자는 언어의 예약어 또는 키워드로 사용되며 일반 식별자로 사용할 수 없습니다. 여기에 쓰여진 대로 정확히 철자를 입력해야 합니다.
False await else import pass
None break except in raise
True class finally is return
and continue for lambda try
as def from nonlocal while
assert del global not with
async elif if or yield
2.3.2. Soft Keywords
버전 3.10의 새로운 기능.
일부 식별자는 특정 컨텍스트에서만 예약됩니다. 이를 소프트 키워드라고 합니다. 식별자 match, case 및 _는 패턴 일치 문과 관련된 컨텍스트에서 키워드로 구문적으로 작동할 수 있지만 이러한 구분은 토큰화할 때가 아니라 구문 분석기 수준에서 수행됩니다.
소프트 키워드로서 일치, 대소문자 및 _를 식별자 이름으로 사용하는 기존 코드와의 호환성을 유지하면서 패턴 일치와 함께 사용할 수 있습니다.
2.3.3. Reserved classes of identifiers
특정 클래스의 식별자(키워드 제외)에는 특별한 의미가 있습니다. 이러한 클래스는 선행 및 후행 밑줄 문자 패턴으로 식별됩니다.
_*
from module import *로 가져오지 않았습니다.
_
일치 문 내의 사례 패턴에서 _는 와일드카드를 나타내는 소프트 키워드입니다.
별도로 대화형 인터프리터는 마지막 평가 결과를 변수 _에서 사용할 수 있도록 합니다. (print와 같은 내장 함수와 함께 builtins 모듈에 저장됩니다.)
다른 곳에서 _는 일반 식별자입니다. “특별한” 항목의 이름을 지정하는 데 자주 사용되지만 Python 자체에는 특별하지 않습니다.
참고:
_라는 이름은 종종 국제화와 함께 사용됩니다. 이 규칙에 대한 자세한 내용은 gettext 모듈에 대한 설명서를 참조하십시오.
또한 일반적으로 사용되지 않는 변수에 사용됩니다.
__*__
비공식적으로 “dunder” 이름으로 알려진 시스템 정의 이름. 이러한 이름은 인터프리터와 그 구현(표준 라이브러리 포함)에 의해 정의됩니다. 현재 시스템 이름은 특수 메서드 이름 섹션 및 다른 곳에서 설명합니다. 향후 버전의 Python에서 더 많이 정의될 것입니다. 명시적으로 문서화된 사용을 따르지 않는 어떤 맥락에서든 이름을 사용하면 경고 없이 손상될 수 있습니다.
__*
클래스 비공개 이름. 이 범주의 이름은 클래스 정의 컨텍스트 내에서 사용되는 경우 기본 클래스와 파생 클래스의 “비공개” 특성 간의 이름 충돌을 방지하기 위해 맹글링된 형식을 사용하도록 다시 작성됩니다. 식별자(이름) 섹션을 참조하십시오.
2.4. Literals
리터럴은 일부 기본 제공 유형의 상수 값에 대한 표기법입니다.
2.4.1. String and Bytes literals¶
문자열 리터럴은 다음 어휘 정의로 설명됩니다.
stringliteral ::= [stringprefix](shortstring | longstring)
stringprefix ::= "r" | "u" | "R" | "U" | "f" | "F"
| "fr" | "Fr" | "fR" | "FR" | "rf" | "rF" | "Rf" | "RF"
shortstring ::= "'" shortstringitem* "'" | '"' shortstringitem* '"'
longstring ::= "'''" longstringitem* "'''" | '"""' longstringitem* '"""'
shortstringitem ::= shortstringchar | stringescapeseq
longstringitem ::= longstringchar | stringescapeseq
shortstringchar ::= <any source character except "\" or newline or the quote>
longstringchar ::= <any source character except "\">
stringescapeseq ::= "\" <any source character>
bytesliteral ::= bytesprefix(shortbytes | longbytes)
bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB"
shortbytes ::= "'" shortbytesitem* "'" | '"' shortbytesitem* '"'
longbytes ::= "'''" longbytesitem* "'''" | '"""' longbytesitem* '"""'
shortbytesitem ::= shortbyteschar | bytesescapeseq
longbytesitem ::= longbyteschar | bytesescapeseq
shortbyteschar ::= <any ASCII character except "\" or newline or the quote>
longbyteschar ::= <any ASCII character except "\">
bytesescapeseq ::= "\" <any ASCII character>
이러한 생성에 의해 표시되지 않는 한 가지 구문 제한은 stringprefix 또는 bytesprefix와 나머지 리터럴 사이에 공백이 허용되지 않는다는 것입니다. 소스 문자 집합은 인코딩 선언에 의해 정의됩니다. 소스 파일에 인코딩 선언이 없으면 UTF-8입니다. 인코딩 선언 섹션을 참조하십시오.
일반 영어: 두 유형의 리터럴 모두 일치하는 작은따옴표(‘) 또는 큰따옴표(“)로 묶을 수 있습니다. 세 개의 작은따옴표 또는 큰따옴표로 구성된 일치하는 그룹으로 묶을 수도 있습니다(일반적으로 삼중따옴표 문자열이라고 함). ) 백슬래시() 문자는 개행 문자, 백슬래시 자체 또는 따옴표 문자와 같이 특별한 의미가 있는 문자를 이스케이프하는 데 사용됩니다.
바이트 리터럴에는 항상 ‘b’ 또는 ‘B’ 접두사가 붙습니다. str 유형 대신 바이트 유형의 인스턴스를 생성합니다. ASCII 문자만 포함할 수 있습니다. 숫자 값이 128 이상인 바이트는 이스케이프로 표현해야 합니다.
문자열 및 바이트 리터럴 모두 선택적으로 문자 ‘r’ 또는 ‘R’ 접두사가 붙을 수 있습니다. 이러한 문자열을 원시 문자열이라고 하며 백슬래시를 리터럴 문자로 취급합니다. 결과적으로 문자열 리터럴에서 원시 문자열의 ‘\U’ 및 ‘\u’ 이스케이프는 특별히 처리되지 않습니다. Python 2.x의 원시 유니코드 리터럴이 Python 3.x와 다르게 작동하므로 ‘ur’ 구문은 지원되지 않습니다.
버전 3.3의 새로운 기능: 원시 바이트 리터럴의 ‘rb’ 접두사가 ‘br’의 동의어로 추가되었습니다.
버전 3.3의 새로운 기능: 이중 Python 2.x 및 3.x 코드베이스의 유지 관리를 단순화하기 위해 유니코드 레거시 리터럴(u’value’)에 대한 지원이 다시 도입되었습니다. 자세한 내용은 PEP 414를 참조하십시오.
접두사에 ‘f’ 또는 ‘F’가 있는 문자열 리터럴은 형식이 지정된 문자열 리터럴입니다. 형식화된 문자열 리터럴을 참조하세요. ‘f’는 ‘r’과 결합할 수 있지만 ‘b’ 또는 ‘u’와는 결합할 수 없습니다. 따라서 형식이 지정된 원시 문자열은 가능하지만 형식이 지정된 바이트 리터럴은 불가능합니다.
삼중 따옴표 리터럴에서 이스케이프되지 않은 줄 바꿈과 따옴표가 허용되고 유지됩니다. 단, 이스케이프되지 않은 따옴표 세 개가 연속으로 리터럴을 종료하는 경우는 예외입니다. (“따옴표”는 리터럴을 여는 데 사용되는 문자, 즉 ‘ 또는 “입니다.)
‘r’ 또는 ‘R’ 접두사가 없으면 문자열 및 바이트 리터럴의 이스케이프 시퀀스는 표준 C에서 사용하는 규칙과 유사한 규칙에 따라 해석됩니다. 인식되는 이스케이프 시퀀스는 다음과 같습니다.
| Escape Sequence | Meaning | Notes |
|---|---|---|
\<newline> | Backslash and newline ignored | (1) |
\\ | Backslash (\) | |
\' | Single quote (') | |
\" | Double quote (") | |
\a | ASCII Bell (BEL) | |
\b | ASCII Backspace (BS) | |
\f | ASCII Formfeed (FF) | |
\n | ASCII Linefeed (LF) | |
\r | ASCII Carriage Return (CR) | |
\t | ASCII Horizontal Tab (TAB) | |
\v | ASCII Vertical Tab (VT) | |
\ooo | Character with octal value ooo | (2,4) |
\xhh | Character with hex value hh | (3,4) |
문자열 리터럴에서만 인식되는 이스케이프 시퀀스는 다음과 같습니다.
| Escape Sequence | Meaning | Notes |
|---|---|---|
\N{name} | Character named name in the Unicode database | (5) |
\uxxxx | Character with 16-bit hex value xxxx | (6) |
\Uxxxxxxxx | Character with 32-bit hex value xxxxxxxx | (7) |
Notes:
1. 새 줄을 무시하기 위해 줄 끝에 백슬래시를 추가할 수 있습니다.
>>> 'This string will not include \
... backslashes or newline characters.'
'This string will not include backslashes or newline characters.'
삼중 인용 문자열이나 괄호 및 문자열 리터럴 연결을 사용하여 동일한 결과를 얻을 수 있습니다.
2. 표준 C에서와 같이 최대 3개의 8진수를 사용할 수 있습니다.
버전 3.11에서 변경: 값이 0o377보다 큰 8진수 이스케이프는 DeprecationWarning을 생성합니다. 향후 Python 버전에서는 SyntaxWarning이 되고 결국에는 SyntaxError가 됩니다.
3. 표준 C와 달리 정확히 두 개의 16진수가 필요합니다.
4. 바이트 리터럴에서 16진수 및 8진수 이스케이프는 주어진 값을 가진 바이트를 나타냅니다. 문자열 리터럴에서 이러한 이스케이프는 주어진 값을 가진 유니코드 문자를 나타냅니다.
5. 버전 3.3에서 변경: 이름 별칭 1에 대한 지원이 추가되었습니다.
6. 정확히 4개의 16진수가 필요합니다.
7. 모든 유니코드 문자는 이 방법으로 인코딩할 수 있습니다. 정확히 8개의 16진수가 필요합니다.
표준 C와 달리 인식되지 않는 모든 이스케이프 시퀀스는 문자열에 변경되지 않은 상태로 남습니다. 즉, 백슬래시가 결과에 남습니다. (이 동작은 디버깅할 때 유용합니다. 이스케이프 시퀀스를 잘못 입력하면 결과 출력이 더 쉽게 깨진 것으로 인식됩니다.) 또한 문자열 리터럴에서만 인식되는 이스케이프 시퀀스가 바이트에 대한 인식되지 않는 이스케이프 범주에 속한다는 점에 유의해야 합니다. 리터럴.
버전 3.6에서 변경: 인식되지 않는 이스케이프 시퀀스는 DeprecationWarning을 생성합니다. 향후 Python 버전에서는 SyntaxWarning이 되고 결국에는 SyntaxError가 됩니다.
원시 리터럴에서도 따옴표는 백슬래시로 이스케이프할 수 있지만 백슬래시는 결과에 남아 있습니다. 예를 들어 r”\””는 백슬래시와 큰따옴표의 두 문자로 구성된 유효한 문자열 리터럴이고 r”\”는 유효한 문자열 리터럴이 아닙니다(원시 문자열도 홀수 백슬래시로 끝날 수 없음). 특히, 원시 리터럴은 단일 백슬래시로 끝날 수 없습니다(백슬래시가 다음 인용 문자를 이스케이프하기 때문입니다. 또한 단일 백슬래시 뒤에 줄 바꿈이 있는 경우 이 두 문자는 줄 연속이 아니라 리터럴의 일부로 해석됩니다. .
2.4.2. String literal concatenation
서로 다른 인용 규칙을 사용하는 여러 인접 문자열 또는 바이트 리터럴(공백으로 구분)이 허용되며 해당 의미는 연결과 동일합니다. 따라서 “hello” ‘world’는 “helloworld”와 동일합니다. 이 기능을 사용하여 필요한 백슬래시 수를 줄이고 긴 문자열을 여러 줄로 편리하게 분할하거나 문자열의 일부에 주석을 추가할 수도 있습니다. 예를 들면 다음과 같습니다.
re.compile("[A-Za-z_]" # letter or underscore
"[A-Za-z0-9_]*" # letter, digit or underscore
)
이 기능은 구문 수준에서 정의되지만 컴파일 타임에 구현됩니다. 런타임에 문자열 식을 연결하려면 ‘+’ 연산자를 사용해야 합니다. 또한 리터럴 연결은 각 구성 요소에 대해 서로 다른 인용 스타일을 사용할 수 있으며(심지어 원시 문자열과 삼중 인용 문자열을 혼합하는 경우도 있음) 형식이 지정된 문자열 리터럴은 일반 문자열 리터럴과 연결할 수 있습니다.
2.4.3. Formatted string literals
버전 3.6의 새로운 기능.
형식이 지정된 문자열 리터럴 또는 f-string은 ‘f’ 또는 ‘F’ 접두사가 붙는 문자열 리터럴입니다. 이러한 문자열에는 중괄호 {}로 구분된 표현식인 대체 필드가 포함될 수 있습니다. 다른 문자열 리터럴은 항상 상수 값을 갖지만 형식이 지정된 문자열은 실제로 런타임에 평가되는 표현식입니다.
이스케이프 시퀀스는 일반 문자열 리터럴과 같이 디코딩됩니다(리터럴이 원시 문자열로도 표시되는 경우 제외). 디코딩 후 문자열 내용의 문법은 다음과 같습니다.
f_string ::= (literal_char | "{{" | "}}" | replacement_field)*
replacement_field ::= "{" f_expression ["="] ["!" conversion] [":" format_spec] "}"
f_expression ::= (conditional_expression | "*" or_expr)
("," conditional_expression | "," "*" or_expr)* [","]
| yield_expression
conversion ::= "s" | "r" | "a"
format_spec ::= (literal_char | NULL | replacement_field)*
literal_char ::= <any code point except "{", "}" or NULL>
이중 중괄호 ‘{{‘ 또는 ‘}}’가 해당하는 단일 중괄호로 대체되는 것을 제외하고 중괄호 외부의 문자열 부분은 문자 그대로 처리됩니다. 단일 여는 중괄호 ‘{‘는 Python 식으로 시작하는 대체 필드를 표시합니다. 평가 후 식 텍스트와 해당 값을 모두 표시하려면(디버깅에 유용함) 식 뒤에 등호 ‘=’를 추가할 수 있습니다. 느낌표 ‘!’로 시작되는 변환 필드 따를 수 있습니다. 콜론 ‘:’으로 시작하는 형식 지정자를 추가할 수도 있습니다. 대체 필드는 닫는 중괄호 ‘}’로 끝납니다.
형식이 지정된 문자열 리터럴의 식은 몇 가지 예외를 제외하고 괄호로 묶인 일반 Python 식처럼 처리됩니다. 빈 식은 허용되지 않으며 람다 식과 대입 식 := 모두 명시적 괄호로 묶어야 합니다. 대체 표현식은 줄 바꿈(예: 삼중 인용 문자열)을 포함할 수 있지만 주석은 포함할 수 없습니다. 각 식은 형식이 지정된 문자열 리터럴이 나타나는 컨텍스트에서 왼쪽에서 오른쪽 순서로 평가됩니다.
버전 3.7에서 변경: Python 3.7 이전에는 async for 절을 포함하는 await 표현식 및 이해가 구현 문제로 인해 형식이 지정된 문자열 리터럴의 표현식에서 불법이었습니다.
등호 ‘=’가 제공되면 출력에 표현식 텍스트, ‘=’ 및 평가된 값이 포함됩니다. 여는 중괄호 ‘{‘ 뒤, 식 내 및 ‘=’ 뒤의 공백은 모두 출력에 유지됩니다. 기본적으로 ‘=’는 지정된 형식이 없는 한 표현식의 repr()이 제공되도록 합니다. 형식이 지정되면 변환 ‘!r’이 선언되지 않는 한 기본적으로 표현식의 str()이 됩니다.
버전 3.8의 새로운 기능: 등호 ‘=’.
변환이 지정된 경우 식을 평가한 결과는 서식을 지정하기 전에 변환됩니다. 변환 ‘!s’는 결과에 대해 str()을 호출하고, ‘!r’은 repr()을 호출하고, ‘!a’는 ascii()를 호출합니다.
그런 다음 결과는 format() 프로토콜을 사용하여 형식화됩니다. 형식 지정자는 표현식 또는 변환 결과의 format() 메서드에 전달됩니다. 형식 지정자가 생략되면 빈 문자열이 전달됩니다. 형식화된 결과는 전체 문자열의 최종 값에 포함됩니다.
최상위 형식 지정자는 중첩된 대체 필드를 포함할 수 있습니다. 이러한 중첩 필드에는 자체 변환 필드 및 형식 지정자가 포함될 수 있지만 더 깊이 중첩된 대체 필드는 포함되지 않을 수 있습니다. 형식 지정자 미니 언어는 str.format() 메서드에서 사용하는 것과 동일합니다.
형식이 지정된 문자열 리터럴은 연결할 수 있지만 대체 필드는 리터럴 간에 분할할 수 없습니다.
형식이 지정된 문자열 리터럴의 몇 가지 예:
>>> name = "Fred"
>>> f"He said his name is {name!r}."
"He said his name is 'Fred'."
>>> f"He said his name is {repr(name)}." # repr() is equivalent to !r
"He said his name is 'Fred'."
>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal("12.34567")
>>> f"result: {value:{width}.{precision}}" # nested fields
'result: 12.35'
>>> today = datetime(year=2017, month=1, day=27)
>>> f"{today:%B %d, %Y}" # using date format specifier
'January 27, 2017'
>>> f"{today=:%B %d, %Y}" # using date format specifier and debugging
'today=January 27, 2017'
>>> number = 1024
>>> f"{number:#0x}" # using integer format specifier
'0x400'
>>> foo = "bar"
>>> f"{ foo = }" # preserves whitespace
" foo = 'bar'"
>>> line = "The mill's closed"
>>> f"{line = }"
'line = "The mill\'s closed"'
>>> f"{line = :20}"
"line = The mill's closed "
>>> f"{line = !r:20}"
'line = "The mill\'s closed" '
일반 문자열 리터럴과 동일한 구문을 공유한 결과 대체 필드의 문자가 외부 형식 문자열 리터럴에 사용된 인용부호와 충돌하지 않아야 합니다.
f"abc {a["x"]} def" # error: outer string literal ended prematurely
f"abc {a['x']} def" # workaround: use different quoting
형식 표현식에는 백슬래시가 허용되지 않으며 오류가 발생합니다.
f"newline: {ord('\n')}" # raises SyntaxError
백슬래시 이스케이프가 필요한 값을 포함하려면 임시 변수를 만듭니다.
>>> newline = ord('\n')
>>> f"newline: {newline}"
'newline: 10'
형식이 지정된 문자열 리터럴은 표현식을 포함하지 않더라도 독스트링으로 사용할 수 없습니다.
def foo():
f"Not a docstring"
foo.__doc__ is None
True
또한 형식화된 문자열 리터럴을 추가한 제안에 대해서는 PEP 498과 관련 형식 문자열 메커니즘을 사용하는 str.format()을 참조하십시오.
2.4.4. Numeric literals
숫자 리터럴에는 정수, 부동 소수점 숫자 및 허수의 세 가지 유형이 있습니다. 복소수 리터럴이 없습니다(복소수는 실수와 허수를 더하여 형성할 수 있음).
숫자 리터럴에는 기호가 포함되지 않습니다. -1과 같은 구문은 실제로 단항 연산자 ‘-‘와 리터럴 1로 구성된 표현식입니다.
2.4.5. Integer literals
정수 리터럴은 다음 어휘 정의로 설명됩니다.
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"
사용 가능한 메모리에 저장할 수 있는 것 외에 정수 리터럴의 길이에는 제한이 없습니다.
리터럴의 숫자 값을 결정할 때 밑줄은 무시됩니다. 가독성을 높이기 위해 숫자를 그룹화하는 데 사용할 수 있습니다. 하나의 밑줄은 숫자 사이와 0x와 같은 기본 지정자 뒤에 나타날 수 있습니다.
0이 아닌 십진수 앞에 오는 0은 허용되지 않습니다. 이것은 Python이 버전 3.0 이전에 사용했던 C 스타일의 8진수 리터럴을 명확하게 하기 위한 것입니다.
정수 리터럴의 몇 가지 예:
7 2147483647 0o177 0b100110111
3 79228162514264337593543950336 0o377 0xdeadbeef
100_000_000_000 0b_1110_0101
버전 3.6에서 변경: 이제 리터럴에서 그룹화 목적으로 밑줄이 허용됩니다.
2.4.6. Floating point literals
부동 소수점 리터럴은 다음 어휘 정의로 설명됩니다.
floatnumber ::= pointfloat | exponentfloat
pointfloat ::= [digitpart] fraction | digitpart "."
exponentfloat ::= (digitpart | pointfloat) exponent
digitpart ::= digit (["_"] digit)*
fraction ::= "." digitpart
exponent ::= ("e" | "E") ["+" | "-"] digitpart
정수 및 지수 부분은 항상 기수 10을 사용하여 해석됩니다. 예를 들어 077e010은 유효하며 77e10과 같은 숫자를 나타냅니다. 부동 소수점 리터럴의 허용 범위는 구현에 따라 다릅니다. 정수 리터럴에서와 같이 숫자 그룹화에 밑줄이 지원됩니다.
부동 소수점 리터럴의 몇 가지 예:
3.14 10. .001 1e100 3.14e-10 0e0 3.14_15_93
버전 3.6에서 변경: 이제 리터럴에서 그룹화 목적으로 밑줄이 허용됩니다.
2.4.7. Imaginary literals
가상 리터럴은 다음 어휘 정의로 설명됩니다.
imagnumber ::= (floatnumber | digitpart) ("j" | "J")
허수 리터럴은 실수부가 0.0인 복소수를 생성합니다. 복소수는 한 쌍의 부동 소수점 숫자로 표현되며 범위에 동일한 제한이 있습니다. 0이 아닌 실수 부분으로 복소수를 생성하려면 여기에 부동 소수점 숫자를 추가합니다(예: (3+4j)). 가상 리터럴의 몇 가지 예:
3.14j 10.j 10j .001j 1e100j 3.14e-10j 3.14_15_93j
2.5. Operators
다음 토큰은 연산자입니다.
+ - * ** / // % @
<< >> & | ^ ~ :=
< > <= >= == !=
2.6. Delimiters
다음 토큰은 문법에서 구분 기호 역할을 합니다.
( ) [ ] { }
, : . ; @ = ->
+= -= *= /= //= %= @=
&= |= ^= >>= <<= **=
마침표는 부동 소수점 및 가상 리터럴에서도 발생할 수 있습니다. 세 마침표의 시퀀스는 줄임표 리터럴로서 특별한 의미를 갖습니다. 목록의 후반부인 증분 할당 연산자는 어휘적으로 구분 기호 역할을 하지만 연산도 수행합니다.
다음 인쇄 ASCII 문자는 다른 토큰의 일부로 특별한 의미를 갖거나 어휘 분석기에 중요합니다.
' " # \
다음 인쇄 ASCII 문자는 Python에서 사용되지 않습니다. 문자열 리터럴 및 주석 외부에서 발생하는 것은 무조건 오류입니다.
$ ? `
Source: https://docs.python.org/3/reference/lexical_analysis.html