《Python 语言参考》笔记 2. 语法分析

2.1. 行结构

2.1.1. 逻辑行
逻辑行的结束是以 NEWLINE 形符表示的。

2.1.2. 物理行
物理行是以一个行终止序列结束的字符序列。(回车/换行/\n)

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. 显式的行拼接
两个或更多个物理行可使用反斜杠字符 () 拼接为一个逻辑行,规则如下: 当一个物理行以一个不在字符串或注释内的反斜杠结尾时,它将与下一行拼接构成一个单独的逻辑行,反斜杠及其后的换行符会被删除。

以反斜杠结束的行不能带有注释。反斜杠不能用来拼接注释。反斜杠不能用来拼接形符,字符串除外 (即原文字符串以外的形符不能用反斜杠分隔到两个物理行)。不允许有原文字符串以外的反斜杠存在于物理行的其他位置。

2.1.6. 隐式的行拼接
圆括号、方括号或花括号以内的表达式允许分成多个物理行,无需使用反斜杠。

隐式的行拼接可以带有注释。后续行的缩进不影响程序结构。后续行也允许为空白行。隐式拼接的行之间不会有 NEWLINE 形符。隐式拼接的行也可以出现于三引号字符串中 (见下);此情况下这些行不允许带有注释。

2.1.7. 空白行
一个只包含空格符,制表符,进纸符或者注释的逻辑行会被忽略 (即不生成 NEWLINE 形符)。在交互模式输入语句时,对空白行的处理可能会因读取-求值-打印循环的具体实现方式而存在差异。在标准交互模式解释器中,一个完全空白的逻辑行 (即连空格或注释都没有) 将会结束一条多行复合语句。

2.1.8. 缩进
一个逻辑行开头处的空白 (空格符和制表符) 被用来计算该行的缩进等级,以决定语句段落的组织结构。

在一个源文件中如果混合使用制表符和空格符缩进,并使得确定缩进层次需要依赖于制表符对应的空格数量设置,则被视为不合规则;此情况将会引发 TabError。

多个连续行各自的缩进层级将会被放入一个堆栈用来生成 INDENT 和 DEDENT 形符,具体说明如下。

在读取文件的第一行之前,先向堆栈推入一个零值;它将不再被弹出。被推入栈的层级数值从底至顶持续增加。每个逻辑行开头的行缩进层级将与栈顶行比较。如果相同,则不做处理。如果新行层级较高,则会被推入栈顶,并生成一个 INDENT 形符。如果新行层级较低,则 应当 是栈中的层级数值之一;栈中高于该层级的所有数值都将被弹出,每弹出一级数值生成一个 DEDENT 形符。在文件末尾,栈中剩余的每个大于零的数值生成一个 DEDENT 形符。

2.1.9. 形符之间的空白
除非是在逻辑行的开头或字符串内,空格符、制表符和进纸符等空白符都同样可以用来分隔形符。如果两个形符彼此相连会被解析为一个不同的形符,则需要使用空白来分隔 (例如 ab 是一个形符,而 a b 是两个形符)。

2.2. 其他形符

除了 NEWLINE, INDENT 和 DEDENT,还存在以下类别的形符: 标识符, 关键字, 字面值, 运算符 以及 分隔符。 空白字符 (之前讨论过的行终止符除外) 不属于形符,而是用来分隔形符。如果存在二义性,将从左至右读取尽可能长的合法字符串组成一个形符。

2.3. 标识符和关键字

标识符的长度没有限制。对大小写敏感。
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 模块中。当不处于交互模式时,_ 无特殊含义也没有预定义。

__*__
系统定义的名称。这些名称由解释器及其实现 (包括标准库) 所定义。现有系统定义名称相关讨论参见 特殊方法名称 等章节。未来的 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 | stringescapeseqlongstringitem  ::=  longstringchar | stringescapeseqshortstringchar ::=  <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 | bytesescapeseqlongbytesitem  ::=  longbyteschar | bytesescapeseqshortbyteschar ::=  <any ASCII character except "\" or newline or the quote>
longbyteschar  ::=  <any ASCII character except "\">
bytesescapeseq ::=  "\" <any ASCII character>

可以用成对单引号 (’) 或双引号 (") 来标示首尾。

字节串字面值总是带有前缀 ‘b’ 或 ‘B’;

字符串和字节串字面值都可以带有前缀 ‘r’ 或 ‘R’;这种字符串被称为 原始字符串 其中的反斜杠会被当作其本身的字面字符来处理。
因此在原始字符串字面值中,’\U’ 和 ‘\u’ 转义形式不会被特殊对待。

包含 ‘f’ 或 ‘F’ 前缀的字符串字面值称为 格式化字符串字面值;

在三引号字面值中,允许存在未经转义的换行和引号 (并原样保留),除非是未经转义的连续三引号,这标示着字面值的结束。

除非带有 ‘r’ 或 ‘R’ 前缀,字符串和字节串字面值中的转义序列会基于类似标准 C 中的转义规则来解读。

2.4.2. 字符串字面值拼接

多个相邻的字符串或字节串字面值 (以空白符分隔),所用的引号可以彼此不同,其含义等同于全部拼接为一体。

2.4.3. 格式化字符串字面值
示例:


>>> 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'
>>> number = 1024
>>> f"{number:#0x}"  # using integer format specifier'0x400'

2.4.4. 数字字面值

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

注意数字字面值并不包含正负号;-1 这样的负数实际上是由单目运算符 ‘-’ 和字面值 1 合成的。

2.4.5. 整型数字面值


integer      ::=  decinteger | bininteger | octinteger | hexintegerdecinteger   ::=  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"

整型数字面值的长度没有限制,能一直大到占满可用内存。

2.4.6. 浮点数字面值

floatnumber   ::=  pointfloat | exponentfloatpointfloat    ::=  [digitpart] fraction | digitpart "."
exponentfloat ::=  (digitpart | pointfloat) exponentdigitpart     ::=  digit (["_"] digit)*
fraction      ::=  "." digitpartexponent      ::=  ("e" | "E") ["+" | "-"] digitpart

注意整型数部分和指数部分在解析时总是以 10 为基数。例如,077e010 是合法的,且表示的数值与 77e10 相同。

2.4.7. 虚数字面值

imagnumber ::=  (floatnumber | digitpart) ("j" | "J")
2.5. 运算符
+       -       *       **      /       //      %      @
<<      >>      &       |       ^       ~       :=
<       >       <=      >=      ==      !=
2.6. 分隔符
(       )       [       ]       {       }
,       :       .       ;       @       =       ->
+=      -=      *=      /=      //=     %=      @=
&=      |=      ^=      >>=     <<=     **=
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值