7.7 KiB
Specific Python
I. 程序结构
按照控制流逐行执行。
II. 语法规则
1. 字符集合
ASCII 编码,区分大小写,中文字符是未定义的,合法字符集如下:
- 标识符(包括变量标识符、函数标识符):26 个小写英语字母,26 个大写英语字母,数码
0
到9
,下划线_
- 标准运算符:加号
+
,减号-
,乘号*
,浮点除/
,整除//
,取模%
- 关系运算符:大于
>
,小于<
,大于等于>=
,小于等于<=
,不等于!=
,等于==
- 增量运算符:加法
+=
,减法-=
,乘法*=
,浮点除/=
,整除//=
,取模%=
- 赋值运算符:赋值
=
- 下标运算符:取下标对象
[]
- 优先级运算符:括号
()
- 分隔符:逗号
,
- 特殊符号:空格
\n
,制表符\t
,注释标识符#
,字符串标识符"
或'
。
2. 关键字
None
True
False
def
return
break
continue
if
elif
else
while
or
and
not
关键字不可作为变量名或函数名。
3. 空白字符
空格、制表符在源文件中可以区分词素 (Token),同时在一行的开头可以表示缩进。
换行符表示新的语句的开始。
缩进在 Python 用于识别代码块,相关问题将在 Parser 中使用 Antlr4 解决,无需考虑相关的实现。
4. 注释
从 #
开始到本行结束的内容都会被作为注释。
5. 标识符
标识符的第一个字符必须是英文字母,第二个字符开始可以是英文字母、数字或者下划线。
标识符区分大小写。长度超过 64
个字符的标识符是未定义的。
6. 常量
-
逻辑常量:
True
为真,False
为假 -
整数常量:
-
整数常量以十进制表示,非十进制的表示为未定义行为
-
整数常量不设负数,负数可以由正数取负号得到
-
Python 中,整数的范围是没有限制的,此处同理,这意味着你必须实现高精度整数
-
首位为
0
的整数常量是未定义的
-
-
浮点数常量:
- 浮点数常量以十进制表示
- 浮点数常量不设负数,负数可以由正数取负号得到
- 拥有前导
0
的浮点数为未定义的,如0001.1
- 含有 e 的浮点数为未定义的,如
1e5
- 以 . 开头的浮点数为未定义的,如
.123
-
字符串常量
- 字符串常量是由双引号
"
或单引号'
括起来的字符串 - 可以由两个字符串拼接而形成新的字符串常量。如
"123""456"
相当于"123456"
- 字符串中的所有字符必须是可示字符 (printable character) 或空格中的一种
- 字符串常量是由双引号
-
空值常量:
None
用来表示变量没有指向任何值
7. 数据类型
-
bool
:只有True
和False
-
int
:高精度整数 -
float
: 与 C++ 中的double
一致 -
str
:字符串,不可修改! -
元组: 具体表现请参考 python (待完善)
8. 表达式
8.1. 基础表达式
基础表达式包括单独出现的常量、变量、函数调用和数组访问。
8.2. 算术表达式
合法的算术运算符包括:+
, -
, *
, /
, //
, %
,具体行为可以参照 C++,特殊行为有:
- 字符串运算符
str + str
表示字符串的拼接str * int
表示字符串的重复str <= str
表示字符串的比较,比较规则同 C++std::string
,>=
,==
等同理
- 除法
/
表示浮点除,即计算结果为浮点数//
表示整除,即计算结果为整数。注意无论正负皆向下取整,例如-5 // 3 = -2
%
表示模运算,无论模数的正负,皆定义为:a % b = a - (a // b) * b
- 比较
==
和!=
会尝试将两边的值转化为相同类型后再进行比较,但并不会转化为str
类型。无法转化时,比较结果为False
。
- 连续比较
- 存在
1<2>3
这样连续的关系运算符,处理方法是将其拆为相邻的比较并用and
连接但每个值最多只计算一次 - 如
a()<b()<c()
,等价于先翻译成a()<b() and b()<c()
再进行计算,a(),b(),c()
最多只调用一次(因为短路运算符)
- 存在
- 逻辑运算符
and
等价于 C++ 中的&&
,or
等价于 C++ 中的||
,not
等价于 C++ 中的!
and
和or
为短路运算符
- 隐式转化
- 运算时如果两个运算数类型不一致,需转化成相同类型之后再进行运算
- 具体转化规则参考 C++
不包含在特殊行为和 C++ 标准中的行为均为未定义行为。
8.3. 赋值表达式
- 给一个变量赋值的意义是将这个变量指向右值,右值不管类型
- 如
a=1,a=”123”,a=1.1
这三条语句依次执行,再输出a
,结果是1.1
,允许变量遮蔽 - 可以给多变量赋值,如
a,b=1,2
意思是a=1,b=2
依次执行,此处或与标准 Python 不同 - 增量赋值即为普通算术运算的简化表达,具体行为参考 C++
8.4. 运算符优先级
从低到高依次为(其中处在相同行的运算符优先级相同)
=
or
and
not
< > <= >= == !=
+ -
* / // %
()
9. 语句
9.1. 变量定义/赋值语句
- 单变量赋值:
var = value
- 连续赋值:
var_1 = var_2 = ... = value
参考[赋值表达式](####8.3. 赋值表达式)。
9.2. 表达式语句
参考[表达式](###8. 表达式)
9.3. 条件语句
if expression_1:
# code block
elif expression_2:
# code block
else expression_3:
# code block
elif
相当于 else if
,else
可以没有。
9.4. 循环语句
while expression:
# code block
9.5. 跳转语句
- 包括
return
,break
,和continue
- 具体行为参考 C++
10. 函数
10.1. 函数定义
def func(parameters):
# code block
-
参数列表如
a, b, c
,变量名之间用逗号分隔,可以为空 -
有些变量可以有默认值,但是都必须出现在无默认值的变量后面
-
函数可以有返回值,也可以没有返回值,无需显示声明。返回值可以为多变量,如
return a, b
10.2. 函数调用
func(parameters)
-
函数调用必须出现在该函数定义后。
-
参数有两种形式:keyword 和 positional
-
Keyword argument 比如
foo(a=1,b=2)
表示传入参数a
的值为1
,b
的值2
-
Positional argument 是指
foo(1,2)
这样按照出现顺序指代参数 -
若一个参数列表中同时有两种参数形式,那么 positional argument 必须出现在 keyword argument 之前。如
foo(1,b=2)
-
-
数据保证递归层数不超过
2000
层
11. 内建函数
-
print
:输出,可以有任意个参数,逐个输出,中间用空格分隔。输出后换行。输出float
保留6
位小数。输出字符串不要输出前后面的引号。如print("123",1.0)
请输出123 1.000000
。 -
int
:将float
或bool
或str
转成int
。 -
float
: 将int
或bool
或str
转成float
。 -
str
: 将int
或float
或bool
转成str
。 -
bool
: 将int
或float
或str
转成bool
。对于str
,如果是""
则为False
,否则为True
。 -
转型类函数都只有一个参数。
12. 作用域
作用域相关规则:
-
与标准 Python 不同,全局变量的生效范围是全部范围(不用 global 关键字即可访问)
-
只有函数的调用会产生新的作用域,作用域的产生请参考 Python
-
没有代码块级作用域,变量注销只发生在函数级作用域退出时
-
全局作用域无需global即可访问,因此,局部变量覆盖全局变量的唯一方式是通过函数参数列表覆盖。