语法分析
Python程序读取的 解析器 。 解析器的输入流 令牌 ,生成的 词法分析程序 。 这一章描述了如何 词法分析程序把一个文件分解成令牌。
Python读取程序文本作为Unicode代码点;一个源文件的编码 可以由一个utf - 8编码声明和违约,看到了吗 PEP 3120 获取详细信息。 如果无法解码,源文件 SyntaxError 是 提高。
行结构
Python程序分为若干 逻辑行 。
逻辑行
的逻辑线路由令牌表示换行符。 语句 不能跨逻辑线路边界除换行符是允许的 语法(如。 在复合语句,语句之间)。 一个逻辑行是 由一个或多个 物理行 按照明确的或 隐式的 线连接 规则。
物理行
一个物理行是一个由行尾字符序列终止 序列。 在源文件中,任何行终止的标准平台 序列可以使用Unix形式使用ASCII低频(换行),窗户 使用ASCII形式序列CR低频(返回后跟换行),或旧的 麦金塔电脑使用ASCII CR(返回)字符形式。 所有这些形式 同样,使用平台无关。
当嵌入Python源代码字符串应该传递给Python api使用 换行字符(标准C约定 \ n 性格, 代表ASCII低频,是换行符)。
注解
评论始于一个散列字符( # ),不是一个字符串的一部分 文字,最后的物理行结束。 评论标志着结束 的逻辑线,除非隐线加入调用规则。 评论 忽视语法;他们没有令牌。
编码声明
如果一个评论在Python脚本的第一或第二行匹配 正则表达式 编码[=:]\ 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编码名称。 的 编码是用于所有的词法分析,包括字符串字面值,评论 和标识符。 编码声明必须出现在自己的一条线。
连接行加入
两个或两个以上的物理线路可能会加入到逻辑线路使用反斜杠 字符( \ ),如下所示:当一个物理行以一个反斜杠 不是字符串或评论的一部分,它是与下面的形成 一个逻辑行,删除反斜杠和下面的行尾 的性格。 例如:
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
一条线以反斜杠结束不能评论。 一个反斜杠不 继续评论。 一个反斜杠不继续令牌除了字符串 文字(即。 ,令牌字符串不能跨越 使用反斜杠)物理行。 一个反斜杠是非法的在一条线 外一个字符串文字。
使用大括号或者是括号
表达式中括号,方括号或大括号可以连接 多个物理行不使用反斜杠。 例如:
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
隐式地继续行可以进行评论。 的缩进 继续行并不重要。 空白延续线是允许的。 行之间没有换行标记隐含的延续。 隐式地 继续行也可以发生在三引号字符串(见下图); 他们不能进行评论。
空白行
一个逻辑行,只包含空格、制表符、进纸键和可能 评论,被忽略(即。 ,没有换行符生成令牌)。 在互动 输入的语句,处理一个空行可能根据不同 实施read-eval-print循环。一个完全空白的逻辑行(即不包含 空格或评论)终止一个多行语句。
缩进
领先的空白(空格和制表符)的开始使用逻辑线路 计算的缩进级别,进而用于确定 语句的分组。
制表符替换(从左到右)由一个八个空格的 总数量的字符,包括更换的倍数 八(这是为了同样的规则使用Unix)。 总数 空格前面的第一个非空白字符然后决定的 缩进。 不能拆分到多个物理行缩进 反斜杠;第一个反斜杠决定了空白 缩进。
缩进被拒绝,如果一个源文件不一致和制表符和空格 在某种程度上使一个标签的意义依赖于价值空间;一个 TabError 在这种情况下长大。
跨平台兼容性注意: 因为文本编辑器的本质 非unix平台上,是不明智的使用空格和制表符的混合物 缩进在一个源文件。 还应该指出的是,不同的 平台可能明确限制最大的缩进级别。
进纸键字符可能出现在一行的开始;它将被忽略 缩进计算。 进纸键字符出现在其他地方 前导空白的一个未定义的效果(例如,他们可能会重置 数到零)的空间。
缩进级别的连续线是用于生成缩进 取消缩进标记,使用堆栈,如下所示。
在读取文件的第一行之前,一个零被推到栈上; 这将永远不会再次出现了。 数字push到栈上 始终严格增加从下到上。 在每一个的开始 逻辑线路,线路的缩进级别而堆栈的顶部。 如果它是平等的,什么也不会发生。 如果是大的,它被推到栈上, 生成一个缩进标记。 如果是小的,它 必须 是其中一个 数字出现在堆栈上;所有数字栈上的更大 弹出,每个数字出现了取消缩进标记生成的。 在 生成的文件,取消缩进标记上的每个剩余数量 堆栈,大于零。
这是一个正确的例子(尽管混淆)缩进的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
(实际上,前三个解析器检测到的错误,只有最后一个 错误发现的词法分析器的缩进 返回 r 做 不匹配的水平从栈中弹出)。
符号之间的空格
除了一开始的一个逻辑行或字符串的空格 字符空间,可以交替使用选项卡并跳页分开 令牌。 两个标记之间需要空格只有他们的连接 否则可以解释为一个不同的标记(如。 ,ab是一个令牌,但是 b是两个令牌)。
其他的符号
除了换行符、缩进和取消缩进、令牌存在以下类别: 标识符 , 关键字 , 文字 , 运营商 , 分隔符 。 空格 字符(除了行结束符,前面所讨论的)没有令牌,但是 划的令牌。 一个令牌由最长的存在模糊性,又在哪里呢 可能的字符串形式的法律令牌,当从左到右读取。
标识符和关键字
标识符(也称为 的名字 通过下面的词汇来描述 定义。
在Python中标识符的语法是基于Unicode标准附件 UAX-31,细化和修改如下定义,见也 PEP 3131 为 进一步的细节。
在ASCII范围内(U + 0001 . . U + 007 f),有效的标识符的字符 在Python 2是一样的。 x:大写和小写字母 一个 通过 Z 、下划线 _ 除了第一个字符,数字 0 通过 9 。
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*">
所有标识符转换为正常形式NFKC在解析;比较 的标识符是基于NFKC。
关键字
以下标识符用作保留字,或 关键字 的 语言,不能用作普通标识符。 他们必须拼写 就像写在这里:
False class finally is return None continue for lambda try True def from nonlocal while and del global not with as elif if or yield assert else import pass break except in raise
保留类标识符
某些类型的标识符(除了关键字)有特殊的含义。 这些 类模式识别的前导和尾随下划线 人物:
- _ *
-
不是进口的 从 模块 进口 * 。 特殊的标识符 _ 使用 在交互式解释器来存储的结果评价;它是 存储在 内置命令 模块。 当没有在交互模式下, _ 没有特别的意义,没有定义。 参见 import语句 。请注意
这个名字 _ 通常用于与国际化; 参考的文档 gettext 模块的更多 本公约的信息。
- _ * _
- 系统定义的名字。 这些名称翻译及其定义 实现(包括标准库)。 目前的系统名称 讨论的 特殊的方法名称 节和其他地方。 更可能会 被定义在未来版本的Python。 任何 使用 _ * _ 名字,在 任何上下文,这并不遵循明确记录的使用,是主题 破损没有警告。
- __ *
- 阶级的名字。 这类名称,使用时的上下文中 类定义,重写使用一种破坏形式来帮助避免名称 “私人”之间的冲突基础和派生类的属性。 参见 标识符(名字) 。
文字
文字符号为内置类型的常量值。
文本字符串和字节
字符串被词法定义如下:
stringliteral ::= [stringprefix](shortstring | longstring) stringprefix ::= "r" | "R" 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" 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 ‘ 逃在原始字符串不是特别对待。
在三引号字符串,保有的换行和引号(并允许 保留),除了三个保有的报价在一行终止字符串。 (一个 “引用”是开放使用的字符字符串,即 ” 或 )。
除非一个 “r” 或 “R” 在字符串的前缀,转义序列 解释根据规则类似于使用标准c 公认的转义序列是:
转义序列 | 意义 | 笔记 |
---|---|---|
\换行符 | 反斜杠和换行符被忽略 | |
\ \ | 反斜杠( \ ) | |
\ ‘ | 单引号( ” ) | |
\ | 双引号( ) | |
、一个 | ASCII贝尔(贝尔) | |
\ b | ASCII退格(BS) | |
\ f | ASCII跳页(FF) | |
\ n | ASCII换行(低频) | |
r \ | ASCII回车(CR) | |
\ t | ASCII水平选项卡(选项卡) | |
v \ | ASCII垂直制表符(VT) | |
\已坏 | 性格与八进制值 已坏 | (1、3) |
\ xhh | 性格与十六进制值 hh | (2、3) |
在字符串转义序列只认可:
转义序列 | 意义 | 笔记 |
---|---|---|
\ N {名称} | 人物命名 的名字 在 Unicode数据库 | |
\ uxxxx | 性格与16位的十六进制值 xxxx | (4) |
\ Uxxxxxxxx | 性格与32位的十六进制值 xxxxxxxx | (5) |
注:
- 在标准C,三个八进制数字被接受。
- 与标准C不同,需要两个十六进制数字。
- 文字在一个字节,十六进制,八进制转义表示字节 给定的值。 在一个字符串中,这些逃脱表示Unicode字符 给定的值。
- 个人代码单元的构成部分代理对可以编码使用 这个转义序列。 究竟四个十六进制数字是必需的。
- 任何Unicode字符可以编码这种方式,但字符以外的基本 多语言平面(BMP)将编码使用一个代理对如果Python 编译使用16位代码单元(默认)。 到底是八个十六进制数字 是必需的。
与标准C不同,所有未被转义序列剩下的字符串 不变,即 反斜杠的字符串 。 (这种行为 当调试有用:如果一个转义序列是错误,由此产生的输出 更容易被认为是打破。) 这也是需要注意的 转义序列只在字符串属于的范畴 识别为字节字符转义。
即使在一个原始字符串,可以用反斜杠转义字符串引号,但是 反斜杠仍在字符串;例如, r 是一个有效的字符串 文字组成的两个人物:一个反斜杠和双引号; r 不是一个有效的字符串(甚至一个原始字符串不能在奇数结束 反斜杠)。 具体地说, 一个原始字符串不能结束在一个反斜杠 (自反斜杠转义字符下面的引用)。 还请注意 一个反斜杠,后跟一个换行符是解释为这两个 字符的字符串, 不 作为一个延续。
字符串连接
多个相邻的文本字符串或字节(由空格分隔),可能 使用不同的引用惯例,允许,他们的意思是相同的 作为他们的连接。 因此, “世界” 相当于 。 这个特性可以用来减少反斜杠 需要把长字符串方便跨长,甚至添加 评论部分的字符串,例如:
re.compile( # letter or underscore # letter, digit or underscore )
注意,这个功能是定义在句法层面,但在实现 编译时间。 必须使用“+”运算符连接字符串表达式 在运行时。 还要注意,文字连接可以使用不同的引用 为每个组件样式(甚至混合原始字符串和三重引用字符串)。
数字
有三种类型的数字字面值:整数,浮点数, 虚数。 没有复杂的文字(复数可以形成 通过添加一个实数和虚数)。
注意数值型的字面值不包括符号;一个短语 1 是 实际上一个表达式由一元运算符的 - - - - - - ”和文字 1 。
整型常量
整数文字被词法定义如下:
integer ::= decimalinteger | octinteger | hexinteger | bininteger decimalinteger ::= nonzerodigit digit* | "0"+ nonzerodigit ::= "1"..."9" digit ::= "0"..."9" octinteger ::= "0" ("o" | "O") octdigit+ hexinteger ::= "0" ("x" | "X") hexdigit+ bininteger ::= "0" ("b" | "B") bindigit+ octdigit ::= "0"..."7" hexdigit ::= digit | "a"..."f" | "A"..."F" bindigit ::= "0" | "1"
没有限制的长度整数文字除了可以成为什么样的人 存储在可用内存。
注意前导零在一个非零的十进制数是不允许的。 这是 与c风格的消歧八进制文字,Python使用之前的版本 3.0。
十进制整数的一些例子:
7 2147483647 0o177 0b100110111 3 79228162514264337593543950336 0o377 0x100000000 79228162514264337593543950336 0xdeadbeef
浮点文字
浮点文字量被词法定义如下:
floatnumber ::= pointfloat | exponentfloat pointfloat ::= [intpart] fraction | intpart "." exponentfloat ::= (intpart | pointfloat) exponent intpart ::= digit+ fraction ::= "." digit+ exponent ::= ("e" | "E") ["+" | "-"] digit+
注意,整数和指数部分总是解释使用基数10。 例如, 077年e010 是合法的,并表示相同的号码是 77年e10汽油 。 的 允许浮点文字量是随具体的范围。 一些 浮点文字量的例子:
3.14 10. .001 1e100 3.14e-10 0e0
注意数值型的字面值不包括符号;一个短语 1 是 实际上一个表达式由一元运算符组成的 - - - - - - 和文字 1 。
虚构的文字
虚构的文字被词法定义如下:
imagnumber ::= (floatnumber | intpart) ("j" | "J")
一个虚构的文字产生一个复数的实部为0.0。 复杂的 数字表示为两个浮点数和有相同的 限制他们的范围。 创建一个与非零的复数 添加一个浮点数,例如, (3 + 4 j) 。 的一些例子 虚构的文字:
3.14j 10.j 10j .001j 1e100j 3.14e-10j
运算符
运营商以下标记:
+ - * ** / // % << >> & | ^ ~ < > <= >= == !=
分隔符
符号作为分隔符的语法如下:
( ) [ ] { } , : . ; @ = += -= *= /= //= %= &= |= ^= >>= <<= **=
这段时间也可以发生在浮点和虚构的文字。 一个序列 的三个时期作为一个省略号文字有着特殊的意义。 下半年 列表,增强的赋值操作符,词法作为分隔符, 而且执行操作。
以下印刷ASCII字符的一部分,其他有特殊的意义 令牌或者其他重要的词法分析器:
‘
以下印刷在Python中ASCII字符不习惯。 他们的 发生外部字符串和注释是一个无条件的错误:
$ ? `