2. 词法分析¶
Python 程序将由一个 解析器 来读取。 输入解析器的是 词元 的流,由 词法分析器 (或称 分词器) 生成。 本章将介绍词法分析器是如何产生词元的。
词法分析器会确定程序文本的 编码格式 (默认为 UTF-8),并将文本解码为 源字符。 如果文本无法解码,将会引发 SyntaxError。
接下来,词法分析器将使用源字符生成词元流。 所生成的词元类型取决于下一个要处理的源字符。 类似地,分析器的其他特殊行为取决于尚未被处理的第一个源字符。 下面的表格给出了这些源字符串的概要,并带有包含更多信息的章节链接。
字符 |
下一词元(或其他相关文档) |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2.1. 行结构¶
Python 程序可以拆分为多个 逻辑行。
2.1.1. 逻辑行¶
逻辑行的结束由词元 NEWLINE 表示。 除非语法允许 NEWLINE (举例来说,在复合语句中的多个语句之前) 否则语句不能跨越逻辑行边界。 逻辑行由一条或多条 物理行 根据 显示 或 隐式 的 行连接 规则构造而成。
2.1.2. 物理行¶
物理行是由使用下列行结束符序列中的一个作为终结的字符序列:
使用 ASCII LF (linefeed) 的 Unix 形式,
使用 ASCII 序列 CR LF (return 加 linefeed) 的 Windows 形式,
使用 ASCII CR (return) 字符的 'Classic Mac OS' 形式。
无论平台如何,这些序列中的每一个都会被替换为单个ASCII LF(换行)字符。(即使在 字符串字面量 中也是如此。)每一行可以使用这些序列中的任何一个;它们在文件内部不需要保持一致。
输入的结束也作为最后一个物理行的隐式终止符。
形式上:
newline: <ASCII LF> | <ASCII CR> <ASCII LF> | <ASCII CR>
2.1.4. 编码声明¶
Python 脚本第一或第二行的注释匹配正则表达式 coding[=:]\s*([-\w.]+) 时,该注释会被当作编码声明;这个表达式的第一组指定了源码文件的编码。编码声明必须独占一行,在第二行时,则第一行必须也是注释。编码表达式的形式如下:
# -*- coding: <encoding-name> -*-
这也是 GNU Emacs 认可的形式,此外,还支持如下形式:
# vim:fileencoding=<encoding-name>
这是 Bram Moolenaar 的 VIM 认可的形式。
如果没有找到编码格式声明,则默认编码格式为 UTF-8。 如果文件的隐式或显式编码格式为 UTF-8,则初始的 UTF-8 字节顺序标记 (b'\xef\xbb\xbf') 会被忽略,而不是成为语法错误。
如果声明了编码格式,该编码格式的名称必须是 Python 可识别的 (参见 标准编码)。 编码格式会被用于所有的词法分析,包括字符串字面量、注释和标识符等。
所有词法分析,包括字符串字面量、注释和标识符,都作用于使用源编码解码的Unicode文本。除了 NUL 控制字符以外的任何Unicode码点都可以出现在Python源代码中。
source_character: <any Unicode code point, except NUL>
2.1.5. 显式拼接行¶
两个及两个以上的物理行可用反斜杠(\)拼接为一个逻辑行,规则如下:以不在字符串或注释内的反斜杠结尾时,物理行将与下一行拼接成一个逻辑行,并删除反斜杠及其后的换行符。例如:
if 1900 < year < 2100 and 1 <= month <= 12 \
and 1 <= day <= 31 and 0 <= hour < 24 \
and 0 <= minute < 60 and 0 <= second < 60: # 看来是个有效的日期
return 1
以反斜杠结尾的行不能包含注释。反斜杠不能用于延续注释内容。除字符串字面量之外,反斜杠不能用于延续标记(即非字符串字面量的标记不能通过反斜杠拆分到物理行的下一行)。在字符串字面量之外的行中,反斜杠出现在其他位置是非法的。
2.1.6. 隐式拼接行¶
圆括号、方括号、花括号内的表达式可以分成多个物理行,不必使用反斜杠。例如:
month_names = ['Januari', 'Februari', 'Maart', # 这些是
'April', 'Mei', 'Juni', # 一年之中
'Juli', 'Augustus', 'September', # 各个月份的
'Oktober', 'November', 'December'] # 荷兰语名称
隐式行拼接可含注释;后续行的缩进并不重要;还支持空的后续行。隐式拼接行之间没有 NEWLINE 标记。三引号字符串支持隐式拼接行(见下文),但不支持注释。
2.1.7. 空白行¶
仅包含空格、制表符、换页符以及可能的注释的逻辑行将被忽略(即不会生成 NEWLINE 标记)。在交互式输入语句时,空行的处理方式可能因读取-求值-打印循环的实现而异。在标准交互式解释器中,完全空白的逻辑行(即不包含任何空白符或注释)会终止多行语句。
2.1.8. 缩进¶
逻辑行开头的空白符(空格符和制表符)用于计算该行的缩进层级,决定语句组块。
制表符(从左至右)被替换为一至八个空格,缩进空格的总数是八的倍数(与 Unix 的规则保持一致)。首个非空字符前的空格数决定了该行的缩进层次。缩进不能用反斜杠进行多行拼接;首个反斜杠之前的空白符决定了缩进的层次。
源文件混用制表符和空格符缩进时,因空格数量与制表符相关,由此产生的不一致将导致不能正常识别缩进层次,从而触发 TabError。
跨平台兼容性说明: 鉴于非 UNIX 平台文本编辑器本身的特性,请勿在源文件中混用制表符和空格符。另外也请注意,不同平台有可能会显式限制最大缩进层级。
行首含换页符时,缩进计算将忽略该换页符。换页符在行首空白符内其他位置的效果未定义(例如,可能导致空格计数重置为零)。
连续行的缩进级别使用一个栈来生成 INDENT 和 DEDENT 标记,规则如下。
Before the first line of the file is read, a single zero is pushed on the stack;
this will never be popped off again. The numbers pushed on the stack will
always be strictly increasing from bottom to top. At the beginning of each
logical line, the line's indentation level is compared to the top of the stack.
If it is equal, nothing happens. If it is larger, it is pushed on the stack, and
one INDENT token is generated. If it is smaller, it must be one of the
numbers occurring on the stack; all numbers on the stack that are larger are
popped off, and for each number popped off a DEDENT token is generated.
At the end of the file, a DEDENT token is generated for each number
remaining on the stack that is larger than zero.
下面的 Python 代码缩进示例虽然正确,但含混不清:
def perm(l):
# 计算由 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): # 错误:第一行有缩进
for i in range(len(l)): # 错误:没有缩进
s = l[:i] + l[i+1:]
p = perm(l[:i] + l[i+1:]) # 错误:非预期的缩进
for x in p:
r.append(l[i:i+1] + x)
return r # 错误:不一致的缩进
(实际上,解析器可以识别前三个错误;只有最后一个错误由词法分析器识别 --- return r 的缩进无法匹配从栈里移除的缩进层级。)
2.1.9. 标记间的空白字符¶
Except at the beginning of a logical line or in string literals, the whitespace characters space, tab and formfeed can be used interchangeably to separate tokens:
whitespace: ' ' | tab | formfeed
Whitespace is needed between two tokens only if their concatenation
could otherwise be interpreted as a different token. For example, ab is one
token, but a b is two tokens. However, +a and + a both produce
two tokens, + and a, as +a is not a valid token.
2.1.10. 结束标记¶
在非交互输入结束时,词法分析器将生成一个 ENDMARKER 词元。
2.2. 其他标记¶
除了 NEWLINE、INDENT 和 DEDENT 之外,还存在以下几类词元: 标识符 和 关键字 (NAME)、字面量 (如 NUMBER 和 STRING),以及其他符号 (运算符 和 分隔符, OP)。 空白字符(除了前面讨论的逻辑行终止符)不是词元,而是用于分隔词元。 在有歧义的情况下,词元由从左到右读取时能形成合法词元的最长可能字符串组成。
2.3. 名称(标识符和关键字)¶
NAME 标记表示 标识符、关键字 和 软关键字。
Names are composed of the following characters:
uppercase and lowercase letters (
A-Zanda-z),the underscore (
_),digits (
0through9), which cannot appear as the first character, andnon-ASCII characters. Valid names may only contain "letter-like" and "digit-like" characters; see Non-ASCII characters in names for details.
名称必须至少包含一个字符,但没有长度上限。大小写敏感。
Formally, names are described by the following lexical definitions:
NAME:name_startname_continue* name_start: "a"..."z" | "A"..."Z" | "_" | <non-ASCII character> name_continue: name_start | "0"..."9" identifier: <NAME, except keywords>
Note that not all names matched by this grammar are valid; see Non-ASCII characters in names for details.
2.3.1. 关键字¶
以下名称被用作该语言的保留字或 关键字,不能用作普通标识符。它们的拼写必须与此处完全一致:
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. 软关键字¶
在 3.10 版本加入.
某些名称仅在特定上下文中保留。这些被称为 软关键字:
这些标识符在特定上下文中语法上作为关键字使用,但这种区分是在解析器层面完成的,而非词法分析(分词)阶段。
作为软关键字,它们能够在用于相应语法的同时仍然保持与用作标识符名称的现有代码的兼容性。
在 3.12 版本发生变更: type 现在是一个软关键字。
2.3.3. 保留的标识符类¶
某些标识符类(除了关键字)具有特殊含义。这些类的命名模式以下划线字符开头,并以下划线结尾:
_*不会被
from module import *所导入。_在
match语句内部的case模式中,_是一个 软关键字,它表示 通配符。在此之外,交互式解释器会将最后一次求值的结果放到变量
_中。 (它与print等内置函数一起被存储于builtins模块。)在其他地方,
_是一个常规标识符。 它常常被用来命名 "特殊" 条目,但对 Python 本身来说毫无特殊之处。__*__系统定义的名称,通常简称为 "dunder" 。这些名称由解释器及其实现(包括标准库)定义。现有系统定义名称相关的论述详见 特殊方法名称 等章节。Python 未来版本中还将定义更多此类名称。任何情况下,任何 不显式遵从
__*__名称的文档用法,都可能导致无警告提示的错误。__*类的私有名称。类定义时,此类名称以一种混合形式重写,以避免基类及派生类的 "私有" 属性之间产生名称冲突。详见 标识符(名称)。
2.3.4. Non-ASCII characters in names¶
Names that contain non-ASCII characters need additional normalization
and validation beyond the rules and grammar explained
above.
For example, ř_1, 蛇, or साँप are valid names, but r〰2,
€, or 🐍 are not.
This section explains the exact rules.
All names are converted into the normalization form NFKC while parsing.
This means that, for example, some typographic variants of characters are
converted to their "basic" form. For example, fiⁿₐˡᵢᶻₐᵗᵢᵒₙ normalizes to
finalization, so Python treats them as the same name:
>>> fiⁿₐˡᵢᶻₐᵗᵢᵒₙ = 3
>>> finalization
3
备注
Normalization is done at the lexical level only.
Run-time functions that take names as strings generally do not normalize
their arguments.
For example, the variable defined above is accessible at run time in the
globals() dictionary as globals()["finalization"] but not
globals()["fiⁿₐˡᵢᶻₐᵗᵢᵒₙ"].
Similarly to how ASCII-only names must contain only letters, digits and
the underscore, and cannot start with a digit, a valid name must
start with a character in the "letter-like" set xid_start,
and the remaining characters must be in the "letter- and digit-like" set
xid_continue.
These sets based on the XID_Start and XID_Continue sets as defined by the
Unicode standard annex UAX-31.
Python's xid_start additionally includes the underscore (_).
Note that Python does not necessarily conform to UAX-31.
A non-normative listing of characters in the XID_Start and XID_Continue
sets as defined by Unicode is available in the DerivedCoreProperties.txt
file in the Unicode Character Database.
For reference, the construction rules for the xid_* sets are given below.
The set id_start is defined as the union of:
Unicode 类别
<Lu>- 大写字母 (包括A到Z)Unicode 类别
<Ll>- 小写字母 (包括a到z)Unicode 类别
<Lt>- 标题大小写字母Unicode 类别
<Lm>- 修饰字母Unicode category
<Lo>- 其他字母Unicode 类别
<Nl>- 数字字母{
"_"} - 下划线<Other_ID_Start>- 在 PropList.txt 中显式定义的用于支持向下兼容的字符集合
The set xid_start then closes this set under NFKC normalization, by
removing all characters whose normalization is not of the form
id_start id_continue*.
The set id_continue is defined as the union of:
id_start(see above)Unicode 类别
<Nd>- 十进制数字(包括0到9)Unicode 类别
<Pc>- 连接标点符号Unicode 类别
<Mn>- 非间距标记Unicode 类别
<Mc>- 间距组合标记<Other_ID_Continue>- 为支持向下兼容性在 PropList.txt 中另一组显式列出的字符集合
Again, xid_continue closes this set under NFKC normalization.
Unicode 类别使用的是 unicodedata 模块中所包含的 Unicode 字符数据库版本。
2.4. 字面量¶
字面量是内置类型常量值的表示法。
2.5. 字符串与字节串字面量¶
字符串字面量是用单引号(')或双引号(")括起来的文本。例如:
"spam"
'eggs'
用于开始字面量的引号也用于终止它,因此字符串字面量只能包含另一个引号(除非使用转义序列,见下文)。例如:
'Say "Hello", please.'
"Don't do that!"
除了这个限制外,引号字符(' 或 ")的选择不影响字面量的解析方式。
在字符串字面量内部,反斜杠(\)字符引入了一个 转义序列,其特殊含义取决于反斜杠后面的字符。例如,\" 表示双引号字符,并且 不 结束字符串:
>>> print("Say \"Hello\" to everyone!")
Say "Hello" to everyone!
有关此类序列的完整列表和更多详细信息,请参见下文的 转义序列。
2.5.1. 三引号字符串¶
字符串也可以用三组匹配的单引号或双引号括起来。这些通常被称为 三引号字符串:
"""这是一个三引号字符串。"""
在三引号字面量中,允许使用未转义的引号(并且会保留),但与起始引号相同的三个连续未转义引号(' 或 ")会终止字面量:
"""这个字符串内有 "引号"。"""
也允许使用未转义的新行,并且会保留:
'''这个三引号字符串
在下一行继续。'''
2.5.2. 字符串前缀¶
字符串字面量可以有一个可选的 前缀,该前缀会影响字面量内容的解析方式,例如:
b"data"
f'{result=}'
允许的前缀有:
详细信息请参见链接部分。
前缀不区分大小写(例如,'B' 与 'b' 效果相同)。 'r' 前缀可以与 'f', 't' 或 'b' 组合使用,因此 'fr', 'rf', 'tr', 'rt', 'br' 和 'rb' 也是有效的前缀。
在 3.3 版本加入: 新增原始字节串 'rb' 前缀,是 'br' 的同义词。
为简化 Python 2.x 和 3.x 双版本代码库的维护工作,重新引入了对 Unicode 传统字面量(u'value')的支持。更多信息请参阅 PEP 414。
2.5.3. 正式语法¶
除了 "f-字符串" 和 "t-字符串" 之外,字符串字面量由以下词法定义描述。
这些定义使用 负向否定前瞻 (!) 来指示结束引号会终止字面量。
STRING: [stringprefix] (stringcontent) stringprefix: <("r" | "u" | "b" | "br" | "rb"), case-insensitive> stringcontent: | "'''" ( !"'''"longstringitem)* "'''" | '"""' ( !'"""'longstringitem)* '"""' | "'" ( !"'"stringitem)* "'" | '"' ( !'"'stringitem)* '"' stringitem:stringchar|stringescapeseqstringchar: <anysource_character, except backslash and newline> longstringitem:stringitem| newline stringescapeseq: "\" <anysource_character>
请注意,与所有词法定义一样,空白符是重要的。特别是,前缀(如果有)必须紧接起始引号。
2.5.4. 转义序列¶
除非存在 'r' 或 'R' 前缀,在字符串和字节串字面值中的转义序列将按照类似于标准 C 所使用的规则进行解读。 可用的转义序列有:
转义序列 |
含意 |
|---|---|
|
|
|
|
|
|
|
|
|
ASCII 响铃(BEL) |
|
ASCII 退格符(BS) |
|
ASCII 换页符(FF) |
|
ASCII 换行符(LF) |
|
ASCII 回车符(CR) |
|
ASCII 水平制表符(TAB) |
|
ASCII 垂直制表符(VT) |
|
|
|
|
|
|
|
|
|
2.5.4.1. 忽略行尾¶
可以在行尾添加一个反斜杠来忽略换行符:
>>> 'This string will not include \
... backslashes or newline characters.'
'This string will not include backslashes or newline characters.'
2.5.4.2. 转义字符¶
要在非 原始 Python 字符串字面量中包含反斜杠,必须将其加倍。\\ 转义序列表示单个反斜杠字符:
>>> print('C:\\Program Files')
C:\Program Files
同样,序列 \' 和 \" 分别表示单引号和双引号字符:
>>> print('\' and \"')
' and "
2.5.4.3. 八进制字符¶
序列 \ooo 表示一个八进制(基数为8)值为 ooo 的*字符*:
>>> '\120'
'P'
最多接受三个八进制数字(0到7)。
在字节串字面量中,字符 表示具有给定值的 字节。在字符串字面量中,它表示具有给定值的Unicode字符。
在 3.11 版本发生变更: 值大于 0o377 (255) 的八进制转义会产生一个 DeprecationWarning。
在 3.12 版本发生变更: 值大于 0o377 (255) 的八进制转义会产生一个 SyntaxWarning。在未来的Python版本中,它们将引发一个 SyntaxError。
2.5.4.4. 十六进制字符¶
序列 \xhh 表示一个十六进制(基数为16)值为 hh 的*字符*:
>>> '\x50'
'P'
与 C 标准不同,必须为两个十六进制数字。
在字节串字面量中,字符 表示具有给定值的 字节。在字符串字面量中,它表示具有给定值的Unicode字符。
2.5.4.5. 命名Unicode字符¶
序列 \N{name} 表示具有给定 name 的Unicode字符:
>>> '\N{LATIN CAPITAL LETTER P}'
'P'
>>> '\N{SNAKE}'
'🐍'
此序列不能出现在 字节串字面量 中。
在 3.3 版本发生变更: Support for name aliases has been added.
2.5.4.6. 十六进制Unicode字符¶
这些序列 \uxxxx 和 \Uxxxxxxxx 表示具有给定十六进制(基数为16)值的Unicode字符。\u 需要正好四个数字;\U 需要正好八个数字。后者可以编码任何Unicode字符。
>>> '\u1234'
'ሴ'
>>> '\U0001f40d'
'🐍'
这些序列不能出现在 字节串字面量 中。
2.5.4.7. 未识别的转义序列¶
与标准C不同,所有未识别的转义序列在字符串中保持不变,即 反斜杠保留在结果中:
>>> print('\q')
\q
>>> list('\q')
['\\', 'q']
请注意,对于字节串字面量,仅在字符串字面量中识别的转义序列(\N...,\u...,\U...)属于未识别的转义类别。
在 3.6 版本发生变更: 未识别的转义序列会产生 DeprecationWarning。
在 3.12 版本发生变更: 未识别的转义序列会产生一个 SyntaxWarning。在未来的Python版本中,它们将引发一个 SyntaxError。
2.5.5. 字节串字面量¶
字节串字面值 总是带有 'b' 或 'B' 前缀;它们会产生 bytes 类型而不是 str 类型的实例。 它们只能包含 ASCII 字符;数值为 128 或以上的字节必须使用转义序列来表示 (通常为 十六进制字符 或 八进制字符):
>>> b'\x89PNG\r\n\x1a\n'
b'\x89PNG\r\n\x1a\n'
>>> list(b'\x89PNG\r\n\x1a\n')
[137, 80, 78, 71, 13, 10, 26, 10]
同样,零字节必须使用转义序列表示(通常是 \0 或 \x00)。
2.5.6. 原始字符串字面量¶
字符串和字节串字面值都可以选择带有字符 'r' 或 'R' 作为前缀;这样的构造分别称为 原始字符串字面值 和 原始字节串字面值 并会将反斜杠视为字面字符。 因此,在原始字符串字面值中,转义序列 不会被特殊对待:are not treated specially:
>>> r'\d{4}-\d{2}-\d{2}'
'\\d{4}-\\d{2}-\\d{2}'
即使在原始字面量中,引号也可以用反斜杠转义,但反斜杠会保留在输出结果里;例如 r"\"" 是由两个字符组成的有效字符串字面量:反斜杠和双引号;r"\" 则不是有效字符串字面量(原始字符串也不能以奇数个反斜杠结尾)。尤其是,原始字面量不能以单个反斜杠结尾 (反斜杠会转义其后的引号)。还要注意,反斜杠加换行在字面量中被解释为两个字符,而 不是 连续行。
2.5.7. f-字符串¶
在 3.6 版本加入.
在 3.8 版本发生变更: Added the debug specifier (=)
在 3.12 版本发生变更: Many restrictions on expressions within f-strings have been removed. Notably, nested strings, comments, and backslashes are now permitted.
A formatted string literal or f-string is a string literal
that is prefixed with 'f' or 'F'.
Unlike other string literals, f-strings do not have a constant value.
They may contain replacement fields delimited by curly braces {}.
Replacement fields contain expressions which are evaluated at run time.
For example:
>>> who = 'nobody'
>>> nationality = 'Spanish'
>>> f'{who.title()} expects the {nationality} Inquisition!'
'Nobody expects the Spanish Inquisition!'
Any doubled curly braces ({{ or }}) outside replacement fields
are replaced with the corresponding single curly brace:
>>> print(f'{{...}}')
{...}
Other characters outside replacement fields are treated like in ordinary string literals. This means that escape sequences are decoded (except when a literal is also marked as a raw string), and newlines are possible in triple-quoted f-strings:
>>> name = 'Galahad'
>>> favorite_color = 'blue'
>>> print(f'{name}:\t{favorite_color}')
Galahad: blue
>>> print(rf"C:\Users\{name}")
C:\Users\Galahad
>>> print(f'''Three shall be the number of the counting
... and the number of the counting shall be three.''')
Three shall be the number of the counting
and the number of the counting shall be three.
Expressions in formatted string literals are treated like regular
Python expressions.
Each expression is evaluated in the context where the formatted string literal
appears, in order from left to right.
An empty expression is not allowed, and both lambda and
assignment expressions := must be surrounded by explicit parentheses:
>>> f'{(half := 1/2)}, {half * 42}'
'0.5, 21.0'
允许在替换字段中重用外层 f-字符串的引号类型:
>>> a = dict(x=2)
>>> f"abc {a["x"]} def"
'abc 2 def'
替换字段中也允许使用反斜杠并会以与在其他场景下相同的方式求值:
>>> a = ["a", "b", "c"]
>>> print(f"List a contains:\n{"\n".join(a)}")
List a contains:
a
b
c
It is possible to nest f-strings:
>>> name = 'world'
>>> f'Repeated:{f' hello {name}' * 3}'
'Repeated: hello world hello world hello world'
Portable Python programs should not use more than 5 levels of nesting.
CPython 实现细节: CPython does not limit nesting of f-strings.
Replacement expressions can contain newlines in both single-quoted and
triple-quoted f-strings and they can contain comments.
Everything that comes after a # inside a replacement field
is a comment (even closing braces and quotes).
This means that replacement fields with comments must be closed in a
different line:
>>> a = 2
>>> f"abc{a # This comment }" continues until the end of the line
... + 3}"
'abc5'
After the expression, replacement fields may optionally contain:
a debug specifier -- an equal sign (
=), optionally surrounded by whitespace on one or both sides;a conversion specifier --
!s,!ror!a; and/ora format specifier prefixed with a colon (
:).
See the Standard Library section on f-strings for details on how these fields are evaluated.
As that section explains, format specifiers are passed as the second argument
to the format() function to format a replacement field value.
For example, they can be used to specify a field width and padding characters
using the Format Specification Mini-Language:
>>> number = 14.3
>>> f'{number:20.7f}'
' 14.3000000'
Top-level format specifiers may include nested replacement fields:
>>> field_size = 20
>>> precision = 7
>>> f'{number:{field_size}.{precision}f}'
' 14.3000000'
These nested fields may include their own conversion fields and format specifiers:
>>> number = 3
>>> f'{number:{field_size}}'
' 3'
>>> f'{number:{field_size:05}}'
'00000000000000000003'
However, these nested fields may not include more deeply nested replacement fields.
Formatted string literals cannot be used as docstrings, even if they do not include expressions:
>>> def foo():
... f"Not a docstring"
...
>>> print(foo.__doc__)
None
参见
PEP 498 -- Literal String Interpolation
PEP 701 -- Syntactic formalization of f-strings
str.format(), which uses a related format string mechanism.
2.5.8. t-strings¶
在 3.14 版本加入.
A template string literal or t-string is a string literal
that is prefixed with 't' or 'T'.
These strings follow the same syntax rules as
formatted string literals.
For differences in evaluation rules, see the
Standard Library section on t-strings
2.5.9. Formal grammar for f-strings¶
F-strings are handled partly by the lexical analyzer, which produces the
tokens FSTRING_START, FSTRING_MIDDLE
and FSTRING_END, and partly by the parser, which handles
expressions in the replacement field.
The exact way the work is split is a CPython implementation detail.
Correspondingly, the f-string grammar is a mix of lexical and syntactic definitions.
Whitespace is significant in these situations:
There may be no whitespace in
FSTRING_START(between the prefix and quote).Whitespace in
FSTRING_MIDDLEis part of the literal string contents.In
fstring_replacement_field, iff_debug_specifieris present, all whitespace after the opening brace until thef_debug_specifier, as well as whitespace immediatelly followingf_debug_specifier, is retained as part of the expression.CPython 实现细节: The expression is not handled in the tokenization phase; it is retrieved from the source code using locations of the
{token and the token after=.
The FSTRING_MIDDLE definition uses
negative lookaheads (!)
to indicate special characters (backslash, newline, {, }) and
sequences (f_quote).
fstring:FSTRING_STARTfstring_middle*FSTRING_ENDFSTRING_START:fstringprefix("'" | '"' | "'''" | '"""') FSTRING_END:f_quotefstringprefix: <("f" | "fr" | "rf"), case-insensitive> f_debug_specifier: '=' f_quote: <the quote character(s) used in FSTRING_START> fstring_middle: |fstring_replacement_field|FSTRING_MIDDLEFSTRING_MIDDLE: | (!"\" !newline!'{' !'}' !f_quote)source_character|stringescapeseq| "{{" | "}}" | <newline, in triple-quoted f-strings only> fstring_replacement_field: | '{'f_expression[f_debug_specifier] [fstring_conversion] [fstring_full_format_spec] '}' fstring_conversion: | "!" ("s" | "r" | "a") fstring_full_format_spec: | ':'fstring_format_spec* fstring_format_spec: |FSTRING_MIDDLE|fstring_replacement_fieldf_expression: | ','.(conditional_expression| "*"or_expr)+ [","] |yield_expression
备注
In the above grammar snippet, the f_quote and FSTRING_MIDDLE rules
are context-sensitive -- they depend on the contents of FSTRING_START
of the nearest enclosing fstring.
Constructing a more traditional formal grammar from this template is left as an exercise for the reader.
The grammar for t-strings is identical to the one for f-strings, with t instead of f at the beginning of rule and token names and in the prefix.
tstring: TSTRING_START tstring_middle* TSTRING_END <rest of the t-string grammar is omitted; see above>
2.6. 数值字面量¶
NUMBER 标记表示数字字面量,共有三种类型:整数、浮点数和虚数。
NUMBER:integer|floatnumber|imagnumber
数字字面量的数值等价于将其作为字符串传递给 int、float 或 complex 类构造函数时的值。注意,这些构造函数的有效输入并不都属于合法的字面量格式。
数字字面量不包含符号;像 -1 这样的短语实际上是由一元运算符 '-' 和字面量 1 组成的表达式。
2.6.1. 整数字面量¶
整数字面量表示整数。例如:
7
3
2147483647
整数字面量的长度没有限制,仅受可用内存的存储能力限制:
7922816251426433759354395033679228162514264337593543950336
下划线可用于对数字进行分组以增强可读性,且在确定字面量的数值时会被忽略。例如,以下字面量是等价的:
100_000_000_000
100000000000
1_00_00_00_00_000
下划线只能出现在数字之间。例如,_123、321_ 和 123__321 均 不是 有效的字面量。
整数可以分别使用前缀 0b、0o 和 0x 指定为二进制(基数 2)、八进制(基数 8)或十六进制(基数 16)。十六进制数字 10 到 15 用字母 A-F 表示,大小写不敏感。例如:
0b100110111
0b_1110_0101
0o177
0o377
0xdeadbeef
0xDead_Beef
下划线可以紧跟在进制前缀之后。例如,0x_1f 是有效的字面量,但 0_x1f 和 0x__1f 不是。
非零十进制数中不允许有前导零。例如,0123 不是有效的字面量。这是为了与 C 风格的八进制字面量区分开,Python 在 3.0 版本之前曾使用这种风格。
形式上,整数字面量由以下词法定义描述:
integer:decinteger|bininteger|octinteger|hexinteger|zerointegerdecinteger:nonzerodigit(["_"]digit)* bininteger: "0" ("b" | "B") (["_"]bindigit)+ octinteger: "0" ("o" | "O") (["_"]octdigit)+ hexinteger: "0" ("x" | "X") (["_"]hexdigit)+ zerointeger: "0"+ (["_"] "0")* nonzerodigit: "1"..."9" digit: "0"..."9" bindigit: "0" | "1" octdigit: "0"..."7" hexdigit:digit| "a"..."f" | "A"..."F"
在 3.6 版本发生变更: 现已支持在字面量中,用下划线分组数字。
2.6.2. 浮点数字面量¶
浮点(float)字面量,例如 3.14 或 1.5,表示 实数的近似值。
它们由 整数 部分和 小数 部分组成,每个部分均由十进制数字构成。两部分由小数点 . 分隔。:
2.71828
4.0
不同于整数字面值,允许带前导零。 例如,077.010 是合法的,并表示与 77.01 相同的数值。
与整数字面量一样,浮点字面量中的数字之间可以使用单个下划线来提高可读性。:
96_485.332_123
3.14_15_93
整数部分或小数部分可以为空,但不能同时为空。例如:
10. # (等同于 10.0)
.001 # (等同于 0.001)
整数部分和小数部分之后可以选择性地跟随一个 指数部分:字母 e 或 E,后面跟一个可选的符号(+ 或 -),以及一个格式与整数和小数部分相同的数字。这里的 e 或 E 表示"乘以10的...次幂":
1.0e3 # (代表 1.0×10³, or 1000.0)
1.166e-5 # (代表 1.166×10⁻⁵, or 0.00001166)
6.02214076e+23 # (代表 6.02214076×10²³ 或 602214076000000000000000)
对于仅包含整数部分和指数部分的浮点字面量,小数点可以省略:
1e3 # (等同于 1.e3 和 1.0e3)
0e0 # (等同于 0)
形式上,浮点字面量由以下词法定义描述:
floatnumber: |digitpart"." [digitpart] [exponent] | "."digitpart[exponent] |digitpartexponentdigitpart:digit(["_"]digit)* exponent: ("e" | "E") ["+" | "-"]digitpart
在 3.6 版本发生变更: 现已支持在字面量中,用下划线分组数字。
2.6.3. 虚数字面量¶
Python 拥有 复数 对象,但没有直接的复数字面量。相反,虚数字面量 表示实部为零的复数。
例如,在数学中,复数 3+4.2i 被写作实数 3 加上虚数 4.2i。Python 使用类似的语法,只是虚数单位写作 j 而非 i:
3+4.2j
这是一个由 整数字面量 3、 运算符 '+' 和 虚数字面量 4.2j 组成的表达式。由于这是三个独立的词法单元,它们之间允许存在空白符:
3 + 4.2j
每个词法单元内部不允许有空白符。特别地,j 后缀不能与其前面的数字分隔开。
j 前面的数字部分与浮点字面量的语法规则相同。因此,以下是有效的虚数字面量:
4.2j
3.14j
10.j
.001j
1e100j
3.14e-10j
3.14_15_93j
与浮点字面量不同,如果虚数部分仅包含整数部分,则小数点可以省略。该数值仍会被计算为浮点数,而非整数:
10j
0j
1000000000000000000000000j # 等同于 1e+24j
j 后缀在语法上是大小写不敏感的。这意味着你可以使用 J 替代:
3.14J # 等同于 3.14j
形式上,虚数字面量由以下词法定义描述:
imagnumber: (floatnumber|digitpart) ("j" | "J")
2.7. 运算符与定界符¶
以下语法定义了 运算符 和 定界符 标记,即通用的 OP 标记类型。 这些标记及其名称的列表 也可在 token 模块文档中找到。
OP: | assignment_operator | bitwise_operator | comparison_operator | enclosing_delimiter | other_delimiter | arithmetic_operator | "..." | other_op assignment_operator: "+=" | "-=" | "*=" | "**=" | "/=" | "//=" | "%=" | "&=" | "|=" | "^=" | "<<=" | ">>=" | "@=" | ":=" bitwise_operator: "&" | "|" | "^" | "~" | "<<" | ">>" comparison_operator: "<=" | ">=" | "<" | ">" | "==" | "!=" enclosing_delimiter: "(" | ")" | "[" | "]" | "{" | "}" other_delimiter: "," | ":" | "!" | ";" | "=" | "->" arithmetic_operator: "+" | "-" | "**" | "*" | "//" | "/" | "%" other_op: "." | "@"
备注
通常,运算符 用于组合 表达式,而 定界符 则用于其他用途。然而,这两类标记之间并没有明确、正式的区分标准。
某些记号既可用作运算符也可用作定界符,具体取决于使用场景。例如,* 既是乘法运算符,也是用于序列解包的定界符;而 @ 既是矩阵乘法运算符,也是引入装饰器的定界符。
对于某些记号而言,其分类界限并不明确。例如,有些人认为 .、( 和 ) 是定界符,而另一些人则将其视为 getattr() 运算符和函数调用运算符。
Python 中的部分运算符(如 and、or 和 not in)使用 关键字 记号而非"符号"(运算符记号)实现。
连续三个点号的序列 (...) 具有表示一个 Ellipsis 字面值的特殊含义。
2.1.3. 注释¶
注释以井号 (
#) 开头,在物理行末尾截止。注意,井号不是字符串字面量。除非应用隐式行拼接规则,否则,注释代表逻辑行结束。句法不解析注释。