2. 词法分析

Python 程序由一个解析器读取。解析器的输入是词法分析器生成的符号流。本章描述词法分析器如何将文件分解为符号。

Python 将程序文本读取为 Unicode 代码点;源文件的编码可以通过编码声明给出,默认值为 UTF-8,有关详细信息,请参见 PEP 3120。如果源文件无法解码,则会引发 SyntaxError

2.1. 行结构

Python 程序被划分为若干个逻辑行

2.1.1. 逻辑行

逻辑行的结尾由符号 NEWLINE 表示。语句不能跨越逻辑行边界,除非语法允许 NEWLINE(例如,在复合语句中的语句之间)。逻辑行由一个或多个物理行构成,遵循显式或隐式行连接规则。

2.1.2. 物理行

物理行是字符序列,以行尾序列终止。在源文件和字符串中,可以使用任何标准平台行终止序列 - Unix 形式使用 ASCII LF(换行符),Windows 形式使用 ASCII 序列 CR LF(回车后跟换行符),或旧的 Macintosh 形式使用 ASCII CR(回车)字符。所有这些形式都可以使用,与平台无关。输入的结尾也作为最后一个物理行的隐式终止符。

在嵌入 Python 时,源代码字符串应使用标准 C 约定传递给 Python API(\n 字符,表示 ASCII LF,是行终止符)。

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’xefxbbxbf’),而不是将其视为语法错误。

如果声明了编码,则编码名称必须被 Python 识别(参见 标准编码)。该编码用于所有词法分析,包括字符串字面量、注释和标识符。

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:   # Looks like a valid date
        return 1

以反斜杠结尾的行不能包含注释。反斜杠不会继续注释。反斜杠不会继续标记,除了字符串字面量(即,除了字符串字面量之外的标记不能使用反斜杠跨物理行拆分)。反斜杠在字符串字面量之外的行的其他位置是非法的。

2.1.6. 隐式行连接

括号、方括号或花括号中的表达式可以拆分到多行物理行上,而无需使用反斜杠。例如

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. 空白行

仅包含空格、制表符、换页符以及可能包含注释的逻辑行将被忽略(即,不会生成 NEWLINE 标记)。在交互式输入语句时,空白行的处理方式可能因 read-eval-print 循环的实现而异。在标准交互式解释器中,完全空白的逻辑行(即,即使不包含空格或注释的逻辑行)也会终止多行语句。

2.1.8. 缩进

逻辑行开头的引导空白(空格和制表符)用于计算行的缩进级别,进而用于确定语句的组合。

制表符被替换(从左到右)为一个到八个空格,使得直到并包括替换的字符总数是 8 的倍数(这与 Unix 使用的规则相同)。第一个非空白字符之前的空格总数决定了行的缩进。缩进不能使用反斜杠拆分到多个物理行上;第一个反斜杠之前的空白决定了缩进。

如果源文件以一种使含义依赖于制表符在空格中的值的方式混合了制表符和空格,则缩进将被拒绝为不一致;在这种情况下,将引发 TabError

跨平台兼容性说明:由于非 UNIX 平台上的文本编辑器的性质,在单个源文件中混合使用空格和制表符进行缩进是不明智的。还应注意,不同的平台可能会明确限制最大缩进级别。

换页符可能出现在行的开头;它将被忽略,用于上面的缩进计算。出现在引导空白中的其他位置的换页符具有未定义的效果(例如,它们可能会将空格计数重置为零)。

连续行的缩进级别用于使用堆栈生成 INDENT 和 DEDENT 标记,如下所示。

在读取文件的首行之前,将一个零压入堆栈;它永远不会被弹出。压入堆栈的数字将始终从底部到顶部严格递增。在每个逻辑行的开头,将行的缩进级别与堆栈的顶部进行比较。如果相等,则不会发生任何事情。如果更大,则将其压入堆栈,并生成一个 INDENT 标记。如果更小,则它必须是堆栈中出现的数字之一;堆栈中所有更大的数字都被弹出,并且对于每个弹出的数字,都会生成一个 DEDENT 标记。在文件末尾,将为堆栈中每个大于零的数字生成一个 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. 标记之间的空白

除了逻辑行开头或字符串字面量中,空格、制表符和换页符可以互换使用来分隔标记。只有当两个标记的连接可能被解释为不同的标记时,它们之间才需要空格(例如,ab 是一个标记,但 a b 是两个标记)。

2.2. 其他标记

除了 NEWLINE、INDENT 和 DEDENT 之外,还存在以下类别的标记:标识符关键字字面量运算符分隔符。空格字符(除了前面讨论的行终止符)不是标记,而是用来分隔标记。在存在歧义的情况下,标记包含从左到右读取时形成合法标记的最长可能字符串。

2.3. 标识符和关键字

标识符(也称为名称)由以下词法定义描述。

Python 中标识符的语法基于 Unicode 标准附件 UAX-31,并根据以下定义进行了详细说明和更改;有关更多详细信息,请参见 PEP 3131

在 ASCII 范围内(U+0001..U+007F),标识符的有效字符与 Python 2.x 中相同:大写和小写字母 AZ,下划线 _,以及除了第一个字符之外,数字 09

Python 3.0 引入了 ASCII 范围之外的附加字符(参见 PEP 3131)。对于这些字符,分类使用 Unicode 字符数据库的版本,该版本包含在 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*">

上面提到的 Unicode 类别代码代表

  • Lu - 大写字母

  • Ll - 小写字母

  • Lt - 标题字母

  • Lm - 修饰字母

  • Lo - 其他字母

  • Nl - 字母数字

  • Mn - 非间距标记

  • Mc - 间距组合标记

  • Nd - 十进制数字

  • Pc - 连接标点符号

  • Other_ID_Start - PropList.txt 中的显式字符列表,用于支持向后兼容性

  • Other_ID_Continue - 同样

所有标识符在解析时都转换为标准形式 NFKC;标识符的比较基于 NFKC。

列出 Unicode 15.0.0 所有有效标识符字符的非规范性 HTML 文件可以在 https://www.unicode.org/Public/15.0.0/ucd/DerivedCoreProperties.txt 找到

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 版本中添加。

某些标识符仅在特定上下文中保留。这些被称为软关键字。标识符 matchcasetype_ 在某些上下文中可以语法上充当关键字,但这种区别是在解析器级别完成的,而不是在标记化时完成的。

作为软关键字,它们在语法中的使用是可能的,同时仍然保持与使用这些名称作为标识符名称的现有代码的兼容性。

matchcase_ 用于 match 语句。 type 用于 type 语句。

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

2.3.3. 保留的标识符类别

某些标识符类别(除了关键字)具有特殊含义。这些类别由开头和结尾下划线字符的模式标识

_*

不被 from module import * 导入。

_

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

另外,交互式解释器在变量 _ 中提供最后一次评估的结果。(它存储在 builtins 模块中,与内置函数如 print 一同。)

在其他地方,_ 是一个普通的标识符。它通常用于命名“特殊”项,但对 Python 本身并不特殊。

注意

名称 _ 通常与国际化一起使用;有关此约定的更多信息,请参阅 gettext 模块的文档。

它也常用于未使用的变量。

__*__

系统定义的名称,非正式地称为“双下划线”名称。这些名称由解释器及其实现(包括标准库)定义。当前的系统名称在 特殊方法名称 部分和其他地方讨论。在 Python 的未来版本中可能会定义更多。任何在任何上下文中使用 __*__ 名称,而不遵循明确记录的使用方式,都可能在没有警告的情况下出现故障。

__*

类私有名称。此类别的名称,在类定义的上下文中使用时,将被重写为使用混淆形式,以帮助避免基类和派生类之间“私有”属性的名称冲突。请参阅部分 标识符(名称)

2.4. 字面量

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

2.4.1. 字符串和字节字面量

字符串字面量由以下词法定义描述

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>

这些生成式没有指明的一个语法限制是,在 stringprefixbytesprefix 与字面量其余部分之间不允许出现空格。源字符集由编码声明定义;如果源文件中没有给出编码声明,则为 UTF-8;请参见第 编码声明 节。

通俗地说:两种类型的字面量都可以用匹配的单引号 (') 或双引号 (") 括起来。它们也可以用匹配的三组单引号或双引号括起来(通常称为三引号字符串)。反斜杠 (\) 字符用于赋予原本普通的字符特殊含义,例如 n,在转义后 (\n) 表示“换行”。它也可以用来转义原本具有特殊含义的字符,例如换行符、反斜杠本身或引号字符。有关示例,请参见下面的 转义序列

字节字面量始终以 'b''B' 为前缀;它们生成 bytes 类型的实例,而不是 str 类型的实例。它们只能包含 ASCII 字符;数值为 128 或更大的字节必须用转义符表示。

字符串和字节字面量都可以选择性地以字母 'r''R' 为前缀;此类字符串称为原始字符串,它们将反斜杠视为字面字符。因此,在字符串字面量中,原始字符串中的 '\U''\u' 转义符不会被特殊处理。鉴于 Python 2.x 的原始 Unicode 字面量的行为与 Python 3.x 的不同,因此不支持 'ur' 语法。

版本 3.3 中新增: 原始字节字面量的 'rb' 前缀已作为 'br' 的同义词添加。

对 Unicode 遗留字面量 (u'value') 的支持已重新引入,以简化对 Python 2.x 和 3.x 代码库的维护。有关详细信息,请参见 PEP 414

在它的前缀中带有 'f''F' 的字符串字面量是格式化字符串字面量;请参见 f-strings'f' 可以与 'r' 结合使用,但不能与 'b''u' 结合使用,因此原始格式化字符串是可能的,但格式化字节字面量是不可能的。

在三引号字面量中,允许使用未转义的换行符和引号(并保留它们),但连续三个未转义的引号将终止字面量。(“引号”是指用于打开字面量的字符,即 '"。)

2.4.1.1. 转义序列

除非存在 'r''R' 前缀,否则字符串和字节字面量中的转义序列将根据类似于标准 C 中使用的规则进行解释。识别的转义序列为

转义序列

含义

备注

\<newline>

反斜杠和换行符被忽略

(1)

\\

反斜杠 (\)

\'

单引号 (')

\"

双引号 (")

\a

ASCII 响铃 (BEL)

\b

ASCII 退格 (BS)

\f

ASCII 换页 (FF)

\n

ASCII 换行 (LF)

\r

ASCII 回车 (CR)

\t

ASCII 水平制表符 (TAB)

\v

ASCII 垂直制表符 (VT)

\ooo

八进制值为 ooo 的字符

(2,4)

\xhh

十六进制值为 hh 的字符

(3,4)

仅在字符串字面量中识别的转义序列为

转义序列

含义

备注

\N{name}

Unicode 数据库中名为 name 的字符

(5)

\uxxxx

16 位十六进制值为 xxxx 的字符

(6)

\Uxxxxxxxx

32 位十六进制值为 xxxxxxxx 的字符

(7)

备注

  1. 可以在行尾添加反斜杠以忽略换行符

    >>> 'This string will not include \
    ... backslashes or newline characters.'
    'This string will not include backslashes or newline characters.'
    

    可以使用 三引号字符串 或括号和 字符串字面量连接 来实现相同的结果。

  2. 与标准 C 一样,最多接受三个八进制数字。

    版本 3.11 中的变更: 大于 0o377 的八进制转义将产生 DeprecationWarning

    版本 3.12 中的变更: 大于 0o377 的八进制转义将产生 SyntaxWarning。在未来的 Python 版本中,它们最终将成为 SyntaxError

  3. 与标准 C 不同,需要恰好两个十六进制数字。

  4. 在字节字面量中,十六进制和八进制转义表示具有给定值的字节。在字符串字面量中,这些转义表示具有给定值的 Unicode 字符。

  5. 版本 3.3 中的变更: 已添加对名称别名 [1] 的支持。

  6. 需要恰好四个十六进制数字。

  7. 任何 Unicode 字符都可以用这种方式编码。需要恰好八个十六进制数字。

与标准 C 不同,所有未识别的转义序列都将保留在字符串中,即 反斜杠将保留在结果中。(这种行为在调试时很有用:如果转义序列输入错误,则生成的输出更容易识别为错误。)还需要注意,仅在字符串字面量中识别的转义序列属于字节字面量的未识别转义类别。

版本 3.6 中的变更: 未识别的转义序列将产生 DeprecationWarning

版本 3.12 中的变更: 未识别的转义序列将产生 SyntaxWarning。在未来的 Python 版本中,它们最终将成为 SyntaxError

即使在原始字面量中,引号也可以用反斜杠转义,但反斜杠会保留在结果中;例如,r"\"" 是一个有效的字符串字面量,包含两个字符:反斜杠和双引号;r"\" 不是一个有效的字符串字面量(即使是原始字符串也不能以奇数个反斜杠结尾)。具体来说,原始字面量不能以单个反斜杠结尾(因为反斜杠将转义后面的引号字符)。还要注意,单个反斜杠后跟换行符被解释为字面量的一部分的这两个字符,而不是行延续。

2.4.2. 字符串字面量连接

允许使用多个相邻的字符串或字节字面量(由空格分隔),可能使用不同的引用约定,它们的含义与其连接相同。因此,"hello" 'world' 等效于 "helloworld"。此功能可用于减少所需的反斜杠数量,方便地将长字符串拆分为多行,甚至为字符串的一部分添加注释,例如

re.compile("[A-Za-z_]"       # letter or underscore
           "[A-Za-z0-9_]*"   # letter, digit or underscore
          )

请注意,此功能是在语法级别定义的,但在编译时实现。‘+’ 运算符必须用于在运行时连接字符串表达式。还要注意,字面量连接可以使用每个组件的不同引用样式(甚至混合原始字符串和三引号字符串),并且格式化字符串字面量可以与普通字符串字面量连接。

2.4.3. f-字符串

在 3.6 版中添加。

一个 格式化字符串字面量f-字符串 是一个以 '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 | replacement_field)*
literal_char      ::=  <any code point except "{", "}" or NULL>

花括号之外的字符串部分按字面意义处理,但任何双花括号 '{{''}}' 将被替换为相应的单个花括号。单个左花括号 '{' 标记一个替换字段,它以 Python 表达式开头。要显示表达式文本及其计算后的值(在调试中很有用),可以在表达式后添加等号 '='。转换字段由感叹号 '!' 引入,可能在后面。格式说明符也可以附加,由冒号 ':' 引入。替换字段以右花括号 '}' 结束。

格式化字符串字面量中的表达式被视为用括号括起来的常规 Python 表达式,但有一些例外。不允许使用空表达式,并且 lambda 和赋值表达式 := 必须用显式括号括起来。每个表达式都在格式化字符串字面量出现的上下文中从左到右依次求值。替换表达式可以在单引号和三引号 f-字符串中包含换行符,并且可以包含注释。在替换字段中,# 之后的所有内容都是注释(即使是闭合括号和引号)。在这种情况下,替换字段必须在不同的行中关闭。

>>> f"abc{a # This is a comment }"
... + 3}"
'abc5'

在版本 3.7 中更改: 在 Python 3.7 之前,由于实现问题,await 表达式和包含 async for 子句的推导式在格式化字符串字面量中的表达式中是非法的。

在版本 3.12 中更改: 在 Python 3.12 之前,f-字符串替换字段中不允许使用注释。

当提供等号 '=' 时,输出将包含表达式文本、'=' 和计算后的值。开括号 '{' 后的空格、表达式内的空格以及 '=' 后的空格都将保留在输出中。默认情况下,'=' 会导致提供表达式的 repr(),除非指定了格式。当指定格式时,它默认为表达式的 str(),除非声明了转换 '!r'

在版本 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-string 引号类型是允许的

>>> a = dict(x=2)
>>> f"abc {a["x"]} def"
'abc 2 def'

在版本 3.12 中更改: 在 Python 3.12 之前,在替换字段内重用与外部 f-string 相同的引号类型是不可能的。

反斜杠也允许在替换字段中使用,并且与任何其他上下文中一样进行评估

>>> a = ["a", "b", "c"]
>>> print(f"List a contains:\n{"\n".join(a)}")
List a contains:
a
b
c

在版本 3.12 中更改: 在 Python 3.12 之前,反斜杠不允许在 f-string 替换字段内使用。

格式化字符串字面量不能用作文档字符串,即使它们不包含表达式。

>>> def foo():
...     f"Not a docstring"
...
>>> foo.__doc__ is None
True

另请参见 PEP 498,了解添加格式化字符串字面量的提案,以及 str.format(),它使用相关的格式字符串机制。

2.4.4. 数字字面量

有三种类型的数字字面量:整数、浮点数和虚数。没有复数字面量(复数可以通过添加实数和虚数来形成)。

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

2.4.5. 整数字面量

整数字面量由以下词法定义描述

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 这样的基数说明符之后。

请注意,非零十进制数中的前导零是不允许的。这是为了与 C 样式的八进制字面量区分开来,Python 在 3.0 版本之前使用过。

一些整数字面量的示例

7     2147483647                        0o177    0b100110111
3     79228162514264337593543950336     0o377    0xdeadbeef
      100_000_000_000                   0b_1110_0101

在版本 3.6 中更改: 下划线现在允许在字面量中用于分组目的。

2.4.6. 浮点数字面量

浮点数字面量由以下词法定义描述

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. 虚数字面量

虚数字面量由以下词法定义描述

imagnumber ::=  (floatnumber | digitpart) ("j" | "J")

虚数字面量会生成一个实部为 0.0 的复数。复数表示为一对浮点数,并且对它们的范围具有相同的限制。要创建一个具有非零实部的复数,请向其添加一个浮点数,例如 (3+4j)。一些虚数字面量的示例

3.14j   10.j    10j     .001j   1e100j   3.14e-10j   3.14_15_93j

2.5. 运算符

以下标记是运算符

+       -       *       **      /       //      %      @
<<      >>      &       |       ^       ~       :=
<       >       <=      >=      ==      !=

2.6. 分隔符

以下标记在语法中用作分隔符

(       )       [       ]       {       }
,       :       .       ;       @       =       ->
+=      -=      *=      /=      //=     %=      @=
&=      |=      ^=      >>=     <<=     **=

句点也可以出现在浮点数和虚数字面量中。三个句点的序列具有作为省略号字面量的特殊含义。列表的后半部分,即增强赋值运算符,在词法上用作分隔符,但也执行操作。

以下可打印 ASCII 字符作为其他标记的一部分具有特殊含义,或者对词法分析器具有其他意义

'       "       #       \

以下可打印 ASCII 字符在 Python 中未使用。它们在字符串字面量和注释之外的出现是无条件错误

$       ?       `

脚注