该篇主要介绍关于python的基础语法知识。
1. 变量和常量
python当中的标识符作为一个变量,只要它不和关键字冲突,并且满足下面的条件。
1. 首字符不能以数字开头,可以用 '_'或者字母开头。
2. 可以为中文, "身高 = 30" 也是合法的。
3. Python是一门动态类型的语言,它不会检查数据类型,在变量声明的时候不需要指定数据类型。同时可以接受其他的数据类型。
python不能从语法上定义常量,从而导致容易使得变量被修改而带来麻烦,所以需要程序员自己去检查或者防范该类错误,这是因为python是动态的解释性语言,它和c、java不一样,在编译期间静态检查出来。
2. 注释:
注释用 '#'
特殊的注释 :
# coding=utf-8
作用是: 设置代码文件的编码集.必须放在第一行或者第二行才生效。
#!/usr/bin/python
作用是:在 unix、linux等系统下指定使用哪个版本的pyhton
pycharm中多行连续注释的快捷键 "ctrl+斜杆"
3. 缩进
在有if、for、while等语句中,不是使用花括号扩起来的,而是使用缩进的方式。
注意下面的例子:
1 if y > 10 : 2 print(y) 3 print(student_score) 4 else: 5 print(y*10) 6 print(_hello)
注意最后的那一句print和if语句不是同一个代码块里面的。
4.模块
python中一个模块就是一个文件。一个模块可以访问另一个模块的元素。来看下面的例子:
有两个模块,分别是module1 和 hello。文件内容如下 ;
module1.py:
1 # coding=utf-8 2 # 示例module1.py 3 4 y = True 5 z = 10.0 6 7 print('进入module1模块')
hello模块访问module1模块的元素。
hello.py:
1 # coding=utf-8 2 # 示例 hello.py 3 4 import module1 5 from module1 import z 6 7 y = 10 8 9 print(y) # 访问当前模块的变量y 10 print(moduel1.y) #访问module1里面的变量y 11 print(z) # 访问module1模块里面的变量z
两种导入方式的差异:
1. import <模块名>
会将模块中的所有代码全部导入过来,访问时需要添加 "模块名." , 如上面例子的hello.py中的 module1.y 来访问 module1里面的y元素
2. from <模块名> import <元素>
访问时不需要添加 "模块名." , 但是需要注意冲突,如果当前模块中有重名的元素,则不能导入。如hello.py中如果也有z元素,则module1的z不能导入,使用的还是当前模块的z
其实模块就是一种特殊的命名空间,用来约束同名的元素。
5.包
如果有两个同名的模块,如何防止命名冲突?那就是使用包(package),作用就是一种命名空间。
创建包:
现在有两个模块hello,它们放在不同的包com.pkg1和com.pkg2中,如下图所示,包是按照文件夹的层次结构管理的,每个包下面会有_init_.py文件,它的作用是告诉解释器这是一个包,里面一般是空的,但也可以编辑d代码。
既然包是一个文件夹加上一个空的_init_.py文件,则可以自己创建宝,推荐使用pycharm工具创建,它会在创建文件夹的时候还创建一个空的_init_.py文件。
5.1 包导入
包创建好后,将两个模块hello放到不同的包com.pkg1和com.pkg2中。com.pkg1的hello模块该如何访问com.pkg2的hello模块?还是需要通过import语句,在模块前面加上包名。例如
1 # coding=utf-8 2 # com.pkg1 hello.py 3 4 y = True 5 z = 10.1 6 7 print('进入com.pkg1 hello.py')
com.pkg2的hello.py:
1 # coding=utf-8 2 # com.pkg2 / hello.py 3 4 import com.pkg1.hello as module1 5 from com.pkg1.hello import z 6 7 y = 20 8 9 print(y) # 访问当前模块的变量y 10 print(module1.y) # 访问com.pkg1.hello模块的变量y 11 print(z) # 访问com.pkg1.hello模块的变量z
代码第1行的import语句导入com.pkg1.hello模块的所有代码元素的时候,由于com.pkg1.hello模块名和当前模块名冲突,因此需要as module1语句为com.pkg1.hello模块取一个别名module1,访问时需要使用 modulle1. 前缀。使用别名的目的是防止发生命名冲突,也就是要导入的z名字的变量在当前模块中已经存在了,所以给z一个别名x
6.代码规范
6.1命名规范
- 包名: 全部小写,中间用 "."隔开,不推荐使用下划线,包名应该具有唯一性,一般使用组织域名等。
- 模块名:全部小写,多个单词构成用 "_"隔开
- 类名:采用大驼峰写法:如 SplitViewController
- 异常名:异常属于类,但应该使用Error作为后缀。如FileNotFoundError
- 变量名:全部小写,多个单词用"_"隔开。变量用于模块内部或者函数内部用 "_"开头;如果是变量类的内部私有使用变量名用 "__"开头。不要使用双下划线开头和结尾的变量,这是python保留的。
- 函数名:和变量名相同。
- 常量名:大写字母,其他和变量名相同。
例子:
test.py
6.2 注释规范
注释语法有3种: 单行注释、多行注释、文档注释。
6.2.1 文件注释
文件注释使用多行注释,一般在文件头使用。通常包括以下内容:版权信息、文件名、所在模块、作者信息、历史版本信息、文件内容和作用等。
6.2.2 文档注释
文档注释就是文档字符串,注释内容能够生成API帮助文档,可以使用python官方的pydoc工具从源码生成这些信息,也可以生成html文件,所有的公有函数、模块、类和方法应该进行文档注释。
文档注释规范推荐使用一对三重双引号(""")包裹起来,而不推荐三重单引号(''')。文档注释的内容应该放在注释的模块、函数的第一条语句。如果文档注释一行能够写完,结束的三重双引号也在同一行。
如果注释内容很长,第一行注释内容留意个空行,结束的三重双引号要单独占一行,并与开始的对齐。
6.2.3 代码注释
代码注释一般使用单行注释和多行注释。
6.2.4 TODO注释
TODO注释是pycharm等工具为源码提供的特殊注释,方便IDE快速定位代码,主流的IDE支持TODO注释。TODO注释一般说明此次有待处理的任务,或者代码没有编写完成。
6.3 导入规范
导入语句在文件顶部,位于模块注释和文档注释之后,模块全局变量和常量之前。每一个导入语句只能导入一个模块。
from import后面可以导入多个代码元素。
- from codeop import x,y,z
导入语句按照通用到特殊的顺序进行分组: 标准库->第三方库->自定义模块,每一组之间有一个空行,组中按照英文字典排序。
6.4 代码排版
代码排版包括空行、空格、断行、缩进等。
- 空行:将逻辑相关的代码分割开,提高可读性。
- 空格:在赋值符号的前后有空格、括号内不应该有空格、参数列表和索引的左括号前不应有空格。
- 缩进:缩进一个级别一般为4个空格。
- 断行:一行代码中最多79个字符,文档注释一行最多72个字符。一般在逗号后隔开、在运算符前面隔开,有括号不要使用续行符。尽量使用括号将断行的内容包住。
(tips:在python中作为续行符使用,但在大、中、小括号中续行是隐式的)
7.数据类型
在python中,所有的数据类型都是类,每一个变量都是类的“实例”。没有基本数据类型的概念,所以整数、浮点、字符串都是类。
python有6种标准数据类型:数字、字符串、列表、元组、集合、字典。列表、元组、集合、字典可以保存多项数据,他们每一种都是一种数据类型。可以将其归为“”“数据结构”。
7.1 数字类型
数字类型有4种:整数类型、浮点类型、复数类型、布尔类型。(布尔实际是整数的一种)
(tips: python3不再区分整数和长整数,只要是整数类型都是长整数)。
- 二进制数: 以 0b或者 0B为前缀
- 八进制数: 以0o或者0O为前缀,第二个为英文字母o,第一个为阿拉伯数字0
- 16进制数: 以0x或者0x为前缀,
7.2 浮点类型
python浮点类型为float,只支持双精度,而且与本机有关。浮点类型可以使用科学计数法,用小写或者大写的e来表示10的指数,如e2表示10的平方。
7.3 复数类型
复数在数学上非常重要,无论是物理或者电气工程中经常使用,python支持复数能够进行良好的科学计算。
例如: 1+2j表示实部为1,虚部为2的复数。
7.4 布尔类型
python中的布尔类型为bool,bool是int类的子类,它有两个值True和False
其他的数据类型可以通过 bool()函数将其转换成为 布尔类型。如None(空对象)、False、0、0.0、0j(复数)、''(空字符串)、[](空列表)、()(空元组)和{}(空字典)这些数值都会
转换成为False,否则为True
7.5 类型转换
类型转换分为 显式类型转换和隐式类型转换。
隐式类型转换规则:
操作数1类型 | 操作数2类型 | 转换后的类型 |
布尔 | 整数 | 整数 |
布尔、整数 | 浮点 | 浮点 |
显式类型转换:
三种数字类型都有自己的转换函数: int()、float()、bool()
7.6 字符串类型
python的字符串类型是 str
字符串的表示方式有3种:
- 普通字符串:采用单引号(')或者双引号(")扩起来的字符串。
- 原始字符串: 在普通字符串前面加r,其中的特殊字符不需要转义,按照字符串的本来面目显示。
- 长字符串: 包括了换行和缩进等排版字符,可以使用三重单引号或者三重双引号包起来。
7.6.1 字符串格式化
在编程的时候,会遇到将其他的类型变量与字符串拼接到一起,并进行格式化输出。例如保留结果后四位右对齐等。在在吃饭格式化时可以使用字符串的format()方法和占位符。
1 # coding=utf-8 2 # format example 3 4 name = 'marry' 5 age = 18 6 7 s1 = '她的年龄是{0}岁'.format(age) 8 s2 = '{0}的年龄是{1)岁'.format(name,age) 9 s3 = '{1}的年龄是{0}岁'.format(age,name) 10 s4 = '{n}的年龄是{a}岁'.format(n=name,a=age) 11 12 # {}表示占位符,format方法的参数会替换占位符的内容。 13 # 占位符可以用参数索引,也可以使用参数的名字表示占位符。 14 15 print(s1) 16 print(s2) 17 print(s3) 18 print(s4)
占位符中还有格式化控制符,对字符串的格式进行更加精准控制。
控制符 | 说明 |
s | 字符串格式 |
d | 十进制整数 |
f、F | 十进制浮点数 |
g、G | 十进制整数或者浮点数 |
e、E | 科学计数法表示浮点数 |
o | 八进制整数 |
x、X | 16进制数 |
格式控制符是位于占位符索引或者占位符名字的后面,之间用冒号分隔。例如{1:d}表示索引为1的占位符参数是十进制整数。
7.6.2 字符串查找
在给定的字符串中查找子字符串是比较常见的操作。字符串类str中提供了find和rfind方法用来查找子字符串,返回值是插值子字符串的所在位置,没有找到返回-1.
下面具体说明find和rfind的具体使用:
- str.find(sub[,start[,end]]) 在索引start和end 之间查找子字符串sub。找到会返回最左端的索引,没有则返回-1,start是开始索引,end是结束索引,两个参数可以省略,start省略表示从头开始,end省略表示查找到字符串结尾,全部省略表示查找整个字符串。
- str.rfind(sub[,start[,end]]) 和find方法类似,区别是返回的是最右端位置的索引,如果在查找的范围内只找到一处子字符串,find和rfind返回值相同。
example:
7.6.3 字符串和数字相互转换
实际编程中,经常用到字符串和数字之间转换。
字符串转换成为数字可以使用int()和float()实现。
int()函数可以指定基数(进制),例如 : int('AB',16) 的结果是171
数字转换成为字符串的函数: str()
str()函数很强大,缺点是不能格式化,如果需要格式化需要使用 format函数
1 '0:.2f'.format(3.24) 2 ':.1f'.format(3.24) 3 ':10.1f'.format(3.24)
占位符可以省略。
8.运算符
运算符分为 一元运算符和二元运算符。
- 一元运算符: - . 表示取相反运算
- 二元运算符:+、-、*、/、%、**、//
8.2 二元运算符
介绍两个比较特殊的运算符:
** : 幂运算,表示求a的b次幂 ,例如 a ** b
//: 地板除法,求小于a除以b商的最大整数。例如 a // b
字符串支持 +和*运算,但不能讲字符串和其他类型数据连接起来。当 *运算符操作字符串时,如果第二操作数是整数,表示字符串重复很多次。
8.3 逻辑运算符
not 、 and 、or
8.4 关系运算符
>= 、==、<=、!=、>、<
8.5 位运算符
&、|、^(位异或)、~、>>、<<
8.6 其他运算符
先介绍两个特殊的运算符: 同一性测试运算符和成员测试运算符,就是判断的意思,结果是布尔值,属于关系运算符。
- 同一性测试运算符: 测试两个对象是否是同一个对象,类似于 ==运算符,不同点是==测试两个对象内容是否相同。用is 和is not 来判断是否是同一对象。
- 成员测试运算符: in和not in ,测试在一个序列对象中是否包含某一个元素。
8.7 运算符优先级
见表格
算术运算符->位运算符->关系运算符->逻辑运算符->赋值运算符
9.控制语句
顺序、循环、分支。
- 分支: if
- 循环: while、for
- 跳转: break、continue、return
分支:
if con1:
elif con2:
···
elif conx:
else:
循环:
for 迭代变量 in 序列:
语句
使用范围:
范围在python中类型是range,表示一个整数序列,创建范围对象的函数是range()函数:
range([start,]stop[,step])
10.数据结构
常见的数据结构有 数组(Array)、集合(Set)、列表(List)、队列(Queue)、链表(Linkdlist)、树(Tree)、栈(Stack)、堆(Heap)、字典(Dictionary)
主要的数据容器有:序列、集合、字典
(tips:python中没有数组结构,因为是动态类型语言,不强制声明变量的数据类型)
10.1 元组
元组是一种序列结构。
10.1.1 序列
序列(sequence)是一种可迭代的元素是有序的可以重复出现的结构。序列可以通过索引访问元素。(例如班级的学号)
序列包括的结构有:列表(list)、字符串(str)、元组(tuple)、范围(range)、字节序列(bytes)。序列可以进行的操作是:索引、分片、加、乘
索引:分为正值索引和负值索引。
0 | -4 | -3 | -2 | -1 |
H | e | l | l | o |
(负值索引:最后一个为-1,第一个为0,中间递减)
0 | 1 | 2 | 3 | 4 |
H | e | l | l | o |
分片:
- [start,end]: 提取片段
- [start,end,step]
10.1.2 创建元组
元组(tuple)是一种不可变序列,一旦创建就不能修改。创建元组可以使用函数 tuple([iterable]) 或者使用逗号将元素隔开。
eg1: tuple([21,32,43,45])
eg2: ('hello','world',12,34)
10.1.3 访问元组
可以使用下标或者分片。还可以进行拆包操作(unpack),就是将元组的元素取出赋值给不同的变量。接受拆包的变量个数应该等于元组个数。
例如;
1 a = ('hello' , 'world' , 1 , 2 , 3 ) 2 str1 ,str2 , n1 , n2 , n3 = a
另外可以使用 _ 表示哪些元素不取值。
例如 : str1 , _ , n1 , n2 , _ = a