2. 词法分析

Python 程序将由一个 解析器 来读取。 输入解析器的是 词元 的流,由 词法分析器 (或称 分词器) 生成。 本章将介绍词法分析器是如何产生词元的。

词法分析器会确定程序文本的 编码格式 (默认为 UTF-8),并将文本解码为 源字符。 如果文本无法解码,将会引发 SyntaxError

接下来,词法分析器将使用源字符生成词元流。 所生成的词元类型取决于下一个要处理的源字符。 类似地,分析器的其他特殊行为取决于尚未被处理的第一个源字符。 下面的表格给出了这些源字符串的概要,并带有包含更多信息的章节链接。

字符

下一词元(或其他相关文档)

  • space

  • tab

  • formfeed

  • CR, LF

  • 反斜杠 (\)

  • 井号 (#)

  • 引号 (', ")

  • ASCII 字母 (a-z, A-Z)

  • 非 ASCII 字符

  • 下划线 (_)

  • 数字 (0-9)

  • 点号 (.)

  • 问号 (?)

  • 货币符 ($)

  • 反引号 (​`​)

  • 控制字符

  • 错误(在字符串字面值和注释之外)

  • 其他可打印字符

  • 文件结束

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.3. 注释

注释以井号 (#) 开头,在物理行末尾截止。注意,井号不是字符串字面量。除非应用隐式行拼接规则,否则,注释代表逻辑行结束。句法不解析注释。

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 平台文本编辑器本身的特性,请勿在源文件中混用制表符和空格符。另外也请注意,不同平台有可能会显式限制最大缩进层级。

行首含换页符时,缩进计算将忽略该换页符。换页符在行首空白符内其他位置的效果未定义(例如,可能导致空格计数重置为零)。

连续行的缩进级别使用一个栈来生成 INDENTDEDENT 标记,规则如下。

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. 其他标记

除了 NEWLINEINDENTDEDENT 之外,还存在以下几类词元: 标识符关键字 (NAME)、字面量 (如 NUMBERSTRING),以及其他符号 (运算符分隔符, OP)。 空白字符(除了前面讨论的逻辑行终止符)不是词元,而是用于分隔词元。 在有歧义的情况下,词元由从左到右读取时能形成合法词元的最长可能字符串组成。

2.3. 名称(标识符和关键字)

NAME 标记表示 标识符关键字软关键字

Names are composed of the following characters:

  • uppercase and lowercase letters (A-Z and a-z),

  • the underscore (_),

  • digits (0 through 9), which cannot appear as the first character, and

  • non-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_start name_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 版本加入.

某些名称仅在特定上下文中保留。这些被称为 软关键字

  • matchcase_match 语句中使用时属于软关键字。

  • typetype 语句中使用时属于软关键字。

这些标识符在特定上下文中语法上作为关键字使用,但这种区分是在解析器层面完成的,而非词法分析(分词)阶段。

作为软关键字,它们能够在用于相应语法的同时仍然保持与用作标识符名称的现有代码的兼容性。

在 3.12 版本发生变更: type 现在是一个软关键字。

2.3.3. 保留的标识符类

某些标识符类(除了关键字)具有特殊含义。这些类的命名模式以下划线字符开头,并以下划线结尾:

_*

不会被 from module import * 所导入。

_

match 语句内部的 case 模式中,_ 是一个 软关键字,它表示 通配符

在此之外,交互式解释器会将最后一次求值的结果放到变量 _ 中。 (它与 print 等内置函数一起被存储于 builtins 模块。)

在其他地方,_ 是一个常规标识符。 它常常被用来命名 "特殊" 条目,但对 Python 本身来说毫无特殊之处。

备注

_ 常用于连接国际化文本;详见 gettext 模块文档。

它还经常被用来命名无需使用的变量。

__*__

系统定义的名称,通常简称为 "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> - 大写字母 (包括 AZ)

  • Unicode 类别 <Ll> - 小写字母 (包括 az)

  • 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> - 十进制数字(包括 09

  • Unicode 类别 <Pc> - 连接标点符号

  • Unicode 类别 <Mn> - 非间距标记

  • Unicode 类别 <Mc> - 间距组合标记

  • <Other_ID_Continue> - 为支持向下兼容性在 PropList.txt 中另一组显式列出的字符集合

Again, xid_continue closes this set under NFKC normalization.

Unicode 类别使用的是 unicodedata 模块中所包含的 Unicode 字符数据库版本。

参见

  • PEP 3131 -- Supporting Non-ASCII Identifiers

  • PEP 672 -- Unicode-related Security Considerations for Python

2.4. 字面量

字面量是内置类型常量值的表示法。

在词法分析方面,Python有 字符串、字节数值 字面量。

其他“字面量”通过 关键字 (NoneTrueFalse) 和特殊的 省略号标记 (...) 进行词法表示。

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 | stringescapeseq
stringchar:      <any source_character, except backslash and newline>
longstringitem:  stringitem | newline
stringescapeseq: "\" <any source_character>

请注意,与所有词法定义一样,空白符是重要的。特别是,前缀(如果有)必须紧接起始引号。

2.5.4. 转义序列

除非存在 'r' 或 'R' 前缀,在字符串和字节串字面值中的转义序列将按照类似于标准 C 所使用的规则进行解读。 可用的转义序列有:

转义序列

含意

\<newline>

字符串转义 - 忽略模式

\\

反斜杠

\'

单引号

\"

双引号

\a

ASCII 响铃(BEL)

\b

ASCII 退格符(BS)

\f

ASCII 换页符(FF)

\n

ASCII 换行符(LF)

\r

ASCII 回车符(CR)

\t

ASCII 水平制表符(TAB)

\v

ASCII 垂直制表符(VT)

\ooo

字符串转义 - 八进制

\xhh

字符串转义 - 十六进制

\N{name}

字符串转义 - 命名字符

\uxxxx

十六进制 Unicode 字符

\Uxxxxxxxx

十六进制 Unicode 字符

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.7 版本发生变更: The await and async for can be used in expressions within f-strings.

在 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, !r or !a; and/or

  • a 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_MIDDLE is part of the literal string contents.

  • In fstring_replacement_field, if f_debug_specifier is present, all whitespace after the opening brace until the f_debug_specifier, as well as whitespace immediatelly following f_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_START fstring_middle* FSTRING_END

FSTRING_START:      fstringprefix ("'" | '"' | "'''" | '"""')
FSTRING_END:        f_quote
fstringprefix:      <("f" | "fr" | "rf"), case-insensitive>
f_debug_specifier:  '='
f_quote:            <the quote character(s) used in FSTRING_START>

fstring_middle:
   | fstring_replacement_field
   | FSTRING_MIDDLE
FSTRING_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_field
f_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

数字字面量的数值等价于将其作为字符串传递给 intfloatcomplex 类构造函数时的值。注意,这些构造函数的有效输入并不都属于合法的字面量格式。

数字字面量不包含符号;像 -1 这样的短语实际上是由一元运算符 '-' 和字面量 1 组成的表达式。

2.6.1. 整数字面量

整数字面量表示整数。例如:

7
3
2147483647

整数字面量的长度没有限制,仅受可用内存的存储能力限制:

7922816251426433759354395033679228162514264337593543950336

下划线可用于对数字进行分组以增强可读性,且在确定字面量的数值时会被忽略。例如,以下字面量是等价的:

100_000_000_000
100000000000
1_00_00_00_00_000

下划线只能出现在数字之间。例如,_123321_123__321不是 有效的字面量。

整数可以分别使用前缀 0b0o0x 指定为二进制(基数 2)、八进制(基数 8)或十六进制(基数 16)。十六进制数字 10 到 15 用字母 A-F 表示,大小写不敏感。例如:

0b100110111
0b_1110_0101
0o177
0o377
0xdeadbeef
0xDead_Beef

下划线可以紧跟在进制前缀之后。例如,0x_1f 是有效的字面量,但 0_x1f0x__1f 不是。

非零十进制数中不允许有前导零。例如,0123 不是有效的字面量。这是为了与 C 风格的八进制字面量区分开,Python 在 3.0 版本之前曾使用这种风格。

形式上,整数字面量由以下词法定义描述:

integer:      decinteger | bininteger | octinteger | hexinteger | zerointeger
decinteger:   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.141.5,表示 实数的近似值

它们由 整数 部分和 小数 部分组成,每个部分均由十进制数字构成。两部分由小数点 . 分隔。:

2.71828
4.0

不同于整数字面值,允许带前导零。 例如,077.010 是合法的,并表示与 77.01 相同的数值。

与整数字面量一样,浮点字面量中的数字之间可以使用单个下划线来提高可读性。:

96_485.332_123
3.14_15_93

整数部分或小数部分可以为空,但不能同时为空。例如:

10.  # (等同于 10.0)
.001  # (等同于 0.001)

整数部分和小数部分之后可以选择性地跟随一个 指数部分:字母 eE,后面跟一个可选的符号(+-),以及一个格式与整数和小数部分相同的数字。这里的 eE 表示"乘以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]
   | digitpart exponent
digitpart: 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 中的部分运算符(如 andornot in)使用 关键字 记号而非"符号"(运算符记号)实现。

连续三个点号的序列 (...) 具有表示一个 Ellipsis 字面值的特殊含义。