Python语言语法描述规范BNF介绍
读官方的 Python 语言参考(The Python Language Reference)需要了解BNF。
BNF(Backus Normal Form:巴科斯范式、Backus范式 ),是一种用递归的思想来表述计算机语言符号集的定义规范。广泛地使用于程序设计语言、指令集、通信协议的语法表示中。大多数程序设计语言或者形式语义方面的教科书都采用巴科斯范式。在各种文献中还存在巴科斯范式的一些变体,如扩展巴科斯范式 EBNF 或扩充巴科斯范式 ABNF。
BNF (Backus Normal Form) is a notation technique for context-free grammars, often used to describe the syntax of languages used in computing.【BNF(Backus Normal Form)是一种上下文无关语法的表示方法,通常用于描述计算语言的语法。】
符号约定如下:
☆ ::= :是“被定义为”的意思;示例:字符串 ::= 用引号包围的字符序列,表示 字符串 就是 用引号包围的字符序列
☆ "...":终结符,即引号中的字符序列本身,并非指代其它字。而终结符双引号 " 用 double_quote 用来表示;示例:函数调用 ::= 名字 "()" 表示 函数的调用 是 由 名字 加上左右括号字符 () 组成;
☆ double_quote :代表终结符 双引号 "; 示例:字符串 ::= double_quote ... double_quote,表示 字符串 是由被字符 " 包围的字符序列组成,即字符串字面量会被放在双引号中 ("");
☆ 在双引号外的字代表着语法部分;示例:基本类型 ::= 字符串 | 数字 | 布尔,表示 字符串 或 数字 或 布尔 都是 基本类型,但 字符串、数字、布尔 具体是什么,由其它 规则定义;
☆ <...>:必选项;示例:名字 ::= [姓] <名> 表示 名字 中的 名 是必须要有的,但 姓 是可有可无的,即:姓 名 是 名字,名 也是 名字;
☆ [...]:可选,可有可无;示例:名字 ::= [姓] <名> 表示 名字 中的 名 是必须要有的,但 姓 是可有可无的,即:姓 名 是 名字,名 也是 名字;
☆ {...}:重复,0 或 任意次重复;示例:AB ::= "a" {"b"},表示 AB 是由 一个 a 后面跟上任意数量(包括0个)个 b 组成,如 a、a b、a bb、a bbb
☆ (...):分组,用来控制表达式的优先级;示例:AX ::= "a" ("m"|"n"),表示 AX 是由 一个 a 后面跟上 m 或 n 组成;
☆ |:替换,即 或 的意思;示例:布尔 ::= "true" | "false",表示 true 或 false 都是 布尔;
☆ ...:表示各种列举或省略的代码片断;示例:a...z 表示 从 a 到 z 的字符,"..." 表示 由 双引号 " 包围起来的任意字符;
☆ 斜体字: 参数,在其它地方有解释;
☆后缀* 表示“对前一项重复0次或更多次”
☆后缀+ 表示“对前一项重复1次或更多次”
☆后缀?表示“对前一项是0或1次”
例、Python中浮点文本的定义是组合几种符号的一个很好的例子:
浮点数字面值词法定义如下( https://docs.python.org/zh-cn/3/reference/lexical_analysis.html#floating ):
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
if 语句 (https://docs.python.org/zh-cn/3.9/reference/compound_stmts.html#if ):
if_stmt ::= "if" assignment_expression ":" suite
("elif" assignment_expression ":" suite)*
["else" ":" suite]
if语句后面的是表达式(expression), 什么是表达式,可以阅读我的另一篇教程表达式, 表达式的后面必须是一个冒号,冒号后面是一个suite。suite 简单地说代表语句块(即一组语句)。
小括号括起来并在后面追加一个*, 这个*表示0个或多个,因此,if语句后面可以没有elif, 也可以有多个elif。
else 语句,用中括号括起来,表示可选,else可以有0个,或者1个。
下面给出一个比较复杂的例子
函数定义——用户自定义函数的定义(https://docs.python.org/zh-cn/3/reference/compound_stmts.html#function ):
funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")"
["->" expression] ":" suite
decorators ::= decorator+
decorator ::= "@" assignment_expression NEWLINE
parameter_list ::= defparameter ("," defparameter)* "," "/" ["," [parameter_list_no_posonly]]
parameter_list_no_posonly ::= defparameter ("," defparameter)* ["," [parameter_list_starargs]]
parameter_list_starargs ::= "*" [parameter] ("," defparameter)* ["," ["**" parameter [","]]]
| "**" parameter [","]
parameter ::= identifier [":" expression]
defparameter ::= parameter ["=" expression]
funcname ::= identifier
python的一个函数定义可以被一个或多个 decorator(装饰器) 表达式所包装,显得有点复杂。
python的一个函数定义可以被一个或多个 decorator(装饰器) 表达式所包装,显得有点复杂。一个不带装饰器的函数:
def func():
pass
带两个装饰器的函数:
@f1(arg)
@f2
def func():
pass
【Python中的pass是空操作语句——不执行任何操作。它适合当语法上需要一条语句但并不需要执行任何代码时用来临时占位。https://docs.python.org/zh-cn/3/reference/simple_stmts.html#the-pass-statement 】