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 时,传入 Python API 的源码字符串应使用标准 C 惯例换行符(\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 字节顺序标志(b'\xef\xbb\xbf'),文件编码也声明为 UTF-8(这是 Microsoft 的 notepad 等软件支持的形式)。

声明的编码名称必须是 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 形符)。交互模式输入语句时,空白行的处理方式可能因读取 - 求值 - 打印循环(REPL)的具体实现方式而不同。标准交互模式解释器中,完全空白的逻辑行(即连空格或注释都没有)将结束多行复合语句。

2.1.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)。这些字符的分类使用 unicodedata 模块中的 Unicode 字符数据库版本。

标识符的长度没有限制,但区分大小写。

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 4.1 中所有可用的标识符字符详见此 HTML 文件 https://www.unicode.org/Public/13.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. 保留的标识符类

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

_*

from module import * 时,不会导入。交互式解释器中,特殊标识符 _ 用于存储最近一次求值的结果;该标识符保存在 builtins 模块里。不处于交互模式时,_ 没有特殊含义,也没有预定义。详见 import 语句

注解

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

__*__

系统定义的名称,通常简称为 "dunder" 。这些名称由解释器及其实现(包括标准库)定义。现有系统定义名称相关的论述详见 特殊方法名称 等章节。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;详见 编码声明

通俗地说:两种字面量都可以用单引号(')或双引号(") 引起来。也可以用三个单引号或双引号引起来(通常称为 三引号字符串)。反斜杠(\)用于特殊字符转义,例如,换行符、反斜杠本身、引号等。

字节串字面量应加前缀 'b''B';生成的是类型 bytes 的实例,不是类型 str 的实例;字节串只能包含 ASCII 字符;字节串的数值大于等于 128 时,必须用转义表示。

字符串和字节串都可以加前缀 'r''R',称为 原始字符串,原始字符串把反斜杠当作原义字符,即不执行转义操作。因此,原始字符串不对 '\U''\u' 进行特殊的转义处理。与 Python 2.x 的源生 unicode 字面量操作不同, Python 3.x 现已不支持 'ur' 句法。

3.3 新版功能: 新增原始字节串 'rb' 前缀,是 'br' 的同义词。

3.3 新版功能: 支持 unicode 字面值(u'value')遗留代码,简化 Python 2.x 和 3.x 并行代码库的维护工作。详见 PEP 414

前缀为 'f''F' 的字符串称为 格式字符串;详见 格式化字符串字面值'f' 可与 'r' 连用,但不能与 'b''u' 连用,因此,可以使用原始格式字符串,但不能使用格式字节串字面量。

三引号字面量可以包含未转义的换行和引号(原样保留),除了用于终止字面量的,三个连在一起的,未转义的引号。("引号" 是启用字面值的字符,可以是 ',也可以是 "。)

如未标注 '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

八进制数 ooo 字符

(1,3)

\xhh

十六进制数 hh 字符

(2,3)

字符串字面量专用转义序列:

转义序列

意义

备注

\N{name}

Unicode 数据库中名称为 name 的字符

(4)

\uxxxx

16位十六进制数 xxxx 码位的字符

(5)

\Uxxxxxxxx

32位16进制数 xxxxxxxx 码位的字符

(6)

注释:

  1. 与标准 C 一致,接受最多三个八进制数码。

  2. 与标准 C 不同,要求必须为两个十六进制数码。

  3. 在字节串字面值中,十六进制数和八进制数转义码以相应数值代表每个字节。在字符串字面值中,这些转义码以相应数值代表每个 Unicode 字符。

  4. 在 3.3 版更改: 加入了对别名 1 的支持。

  5. 要求必须为四个十六进制数码。

  6. 此方式可用来表示任意 Unicode 字符。要求必须为八个十六进制数码。

与标准 C 不同,所有无法识别的转义序列将原样保留在字符串中,也就是说,反斜杠会在结果中保留。(这种方式在调试时很有用: 如果输错了一个转义序列,更容易在输出结果中识别错误。) 另外要注意的一个关键点是:专用于字符串字面值中的转义序列如果在字节串字面值中出现,会被归类为无法识别的转义序列。

在 3.6 版更改: 无法识别的转义序列将引发 DeprecationWarning。 在某个未来的 Python 版本中它们将引发 SyntaxWarning 并最终将改为引发 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. 格式化字符串字面值

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 表达式一样处理,但有少数例外。 空表达式不被允许,lambda 和赋值表达式 := 必须显式地加上圆括号。 替换表达式可以包含换行(例如在三重引号字符串中),但是不能包含注释。 每个表达式会在格式化字符串字面值所包含的位置按照从左至右的顺序被求值。

在 3.7 版更改: 在 Python 3.7 之前, await 表达式包含 async for 子句的推导式不允许在格式化字符串字面值表达式中使用,这是因为具体实现存在一个问题。

在提供了等于号 '=' 的时候,输出将包含表达式文本,'=' 以及求值结果。 左花括号 '{' 之后包含在表达式中及 '=' 后的空格将在输出时被保留。 默认情况下,'=' 会导致表达式的 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"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. 数字字面值

数字字面值有三种类型: 整型数、浮点数和虚数。没有专门的复数字面值 (复数可由一个实数加一个虚数合成)。

注意数字字面值并不包含正负号;-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 之后。

注意非零的十进制数开头不允许有额外的零。这是为了避免与 Python 在版本 3.0 之前所使用的 C 风格八进制字面值相混淆。

一些整型数字面值的示例如下:

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 词法中使用。如果出现于字符串字面值和注释之外将无条件地引发错误:

$       ?       `

脚注

1

https://www.unicode.org/Public/11.0.0/ucd/NameAliases.txt