Python程序可以拆分为多个逻辑行,以提高代码的可读性和可维护性。
一、逻辑行
NEWLINE 形符表示结束逻辑行。语句不能超出逻辑行的边界,除非句法支持 NEWLINE (例如,复合语句中的多行子语句)。根据显式或隐式 行拼接 规则,一个或多个 物理行 可组成逻辑行。
二、物理行
物理行是由一序列字符组成,由行尾序列终止。源文件和字符串可以使用任意标准平台的行终止序列,包括 Unix ASCII 字符 LF(换行)、Windows ASCII 字符序列 CR LF(回车换行)或老式 Macintosh ASCII 字符 CR(回车)。无论在哪个平台上,这些形式都可以等价使用。输入结束也可以用作最终物理行的隐式终止符。
在嵌入 Python 时,将源码字符串传递给 Python API 时,应使用 C 标准惯例的换行符(\n),它代表 ASCII 字符 LF,作为行终止符。
三、注释
注释以井号(#)开头,并在物理行末尾截止。需要注意的是,井号不是字符串字面值。除非应用隐式行拼接规则,否则注释代表逻辑行的结束。语法解析器不会解析注释。
四、编码声明
当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 可识别的。 编码格式会被用于所有的词法分析,包括字符串字面值、注释和标识符等。
五、显式拼接行
两个及两个以上的物理行可用反斜杠(\)拼接为一个逻辑行,规则如下:
以不在字符串或注释内的反斜杠结尾时,物理行将与下一行拼接成一个逻辑行,并删除反斜杠及其后的换行符:
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
隐式行拼接允许在一行内包含注释。后续行的缩进并不重要,还可以有空的后续行。隐式拼接行之间没有 NEWLINE 字符。三引号字符串支持隐式拼接行,但不支持注释。
七、空白行
只包含空格符、制表符、换页符、注释的逻辑行会被忽略(即不生成 NEWLINE 形符)。交互模式输入语句时,空白行的处理方式可能因读取 – 求值 – 打印循环(REPL)的具体实现方式而不同。标准交互模式解释器中,完全空白的逻辑行(即连空格或注释都没有)将结束多行复合语句。
八、缩进
逻辑行开头的空白符(空格符和制表符)用于计算该行的缩进层级,以确定语句组块。制表符(从左至右)会被替换为一至八个空格,缩进空格的总数是八的倍数(与 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 的缩进无法匹配从栈里移除的缩进层级。)
九、形符间的空白字符
除非在逻辑行开头或字符串内,空格符、制表符、换页符等空白符都可以分隔形符。要把两个相连形符解读为不同形符,需要用空白符分隔(例如,ab 是一个形符,a b 则是两个形符)。