⭐️0. 培训前言
对于测试工程师,有时会遇到大量且重复枯燥的工作,这个时候我们如果能用脚本让计算机帮助我们批量处理,将会大大节省我们宝贵的时间,抽身做其他更有意义,更具创新、更有挑战、更有意义的事情。平时脚本多会使用到 c
、python
、perl
语言,其中 python
简单好用,具有很多的现成库,我们就以 python
语言作为培训内容。
⭐️1. 环境准备
本次使用微软的 VS Code
+ Python3.9.6
进行培训,下面介绍开发环境搭建过程。
- 点击【链接】下载
VS Code
安装包,直接按照提示进行安装即可。 - 点击【链接】下载
Python3.9.6
安装包,参照【python3安装教程】进行安装 - 将安装源改为国内阿里,
win + R
输入cmd
,然后根据需要输入以下命令:
# 若你只有一个python
pip config set global.index-url http://mirrors.aliyun.com/pypi/simple
pip config set global.trusted-host mirrors.aliyun.com
# 若你安装了两个版本的python
pip2 config set global.index-url http://mirrors.aliyun.com/pypi/simple
pip2 config set global.trusted-host mirrors.aliyun.com
pip3 config set global.index-url http://mirrors.aliyun.com/pypi/simple
pip3 config set global.trusted-host mirrors.aliyun.com
VS Code
安装以下插件,提高编程效率:
Chinese
Code Runner
Bracket Pair Colorizer
Image preview
Prettier - Code formatter
Python
Pylance
Tabnine
vscode-icons
vscode-pdf
vscode-yarkdown
Better C++ Syntax
markdown
C/C++
C/C++ Extension Pack
C/C++ Themes
C++ Intellisense
其它插件请大家自行探索。。。
VS Code
快捷键:
注释/取消/添加注释:ctrl + /
关闭打开侧边栏:ctrl + B
代码整体缩进:选中多行代码,TAB
代码整体向前缩进:选中多行代码,Shift + TAB
⭐️2. python基础
2.1 基础语法
- 关键字,就比如c语言中的
while
和for
一样,你不能定义的变量名为while
,这样会编译报错。
# 以下关键字我们不能使用
import keyword
print(keyword.kwlist)
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
- 多行注释可以用多个
#
号,还有'''
和"""
。 - python使用缩进(4个空格)来替代C语言的
{}
,所以python代码需要设置好严格的缩进。 - 打印输出
print
,键盘输入input
。 - python的每个语句后面不需要
;
,但是如果一行写多个语句,则需要添加;
。 import
与from xxx import xxx
:
# 假设math文件里面定义了一个名为sin的函数,我们想使用sin函数可以有以下两种方式:
import math
print(math.sin(math.pi))
from math import sin,pi
print(sin(pi))
2.2 运算符
- 算术运算符
以下假设变量 a=10,变量 b=21:
运算符 | 描述 | 实例 |
---|---|---|
+ | 加 - 两个对象相加 | a + b 输出结果 31 |
- | 减 - 得到负数或是一个数减去另一个数 | a - b 输出结果 -11 |
* | 乘 - 两个数相乘或是返回一个被重复若干次的字符串 | a * b 输出结果 210 |
/ | 除 - x 除以 y | b / a 输出结果 2.1 |
% | 取模 - 返回除法的余数 | b % a 输出结果 1 |
** | 幂 - 返回x的y次幂 | a**b 为10的21次方 |
// | 取整除 - 向下取接近商的整数 | 9//2=4 |
- 比较运算符
以下假设变量a为10,变量b为20:
运算符 | 描述 | 实例 |
---|---|---|
== | 等于 - 比较对象是否相等 | (a == b) 返回 False。 |
!= | 不等于 - 比较两个对象是否不相等 | (a != b) 返回 True。 |
> | 大于 - 返回x是否大于y | (a > b) 返回 False。 |
< | 小于 - 返回x是否小于y。所有比较运算符返回1表示真,返回0表示假。这分别与特殊的变量True和False等价。注意,这些变量名的大写。 | (a < b) 返回 True。 |
>= | 大于等于 - 返回x是否大于等于y。 | (a >= b) 返回 False。 |
<= | 小于等于 - 返回x是否小于等于y。 | (a <= b) 返回 True。 |
- 赋值运算符
以下假设变量a为10,变量b为20:
运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符 | c = a + b 将 a + b 的运算结果赋值为 c |
+= | 加法赋值运算符 | c += a 等效于 c = c + a |
-= | 减法赋值运算符 | c -= a 等效于 c = c - a |
*= | 乘法赋值运算符 | c *= a 等效于 c = c * a |
/= | 除法赋值运算符 | c /= a 等效于 c = c / a |
%= | 取模赋值运算符 | c %= a 等效于 c = c % a |
**= | 幂赋值运算符 | c **= a 等效于 c = c ** a |
//= | 取整除赋值运算符 | c //= a 等效于 c = c // a |
:= | 海象运算符,可在表达式内部为变量赋值。Python3.8 版本新增运算符。 | 在这个示例中,赋值表达式可以避免调用 len() 两次:if (n := len(a)) > 10: print(f"List is too long ({n} elements, expected <= 10)") |
- 位运算符
按位运算符是把数字看作二进制来进行计算的。Python中的按位运算法则如下:
下表中变量 a 为 60,b 为 13二进制格式如下:
运算符 | 描述 | 实例 |
---|---|---|
& | 按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0 | (a & b) 输出结果 12 ,二进制解释: 0000 1100 |
| | 按位或运算符:只要对应的二个二进位有一个为1时,结果位就为1。 | (a| b) 输出结果 61 ,二进制解释: 0011 1101 |
^ | 按位异或运算符:当两对应的二进位相异时,结果为1 | (a ^ b) 输出结果 49 ,二进制解释: 0011 0001 |
~ | 按位取反运算符:对数据的每个二进制位取反,即把1变为0,把0变为1。~x 类似于 -x-1 | (~a ) 输出结果 -61 ,二进制解释: 1100 0011, 在一个有符号二进制数的补码形式。 |
<< | 左移动运算符:运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。 | a << 2 输出结果 240 ,二进制解释: 1111 0000 |
>> | 右移动运算符:把">>“左边的运算数的各二进位全部右移若干位,”>>"右边的数指定移动的位数 | a >> 2 输出结果 15 ,二进制解释: 0000 1111 |
- 逻辑运算符
Python语言支持逻辑运算符,以下假设变量 a 为 10, b为 20:
运算符 | 逻辑表达式 | 描述 | 实例 |
---|---|---|---|
and | x and y | 布尔"与" - 如果 x 为 False,x and y 返回 x 的值,否则返回 y 的计算值。 | (a and b) 返回 20。 |
or | x or y | 布尔"或" - 如果 x 是 True,它返回 x 的值,否则它返回 y 的计算值。 | (a or b) 返回 10。 |
not | not x | 布尔"非" - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。 | not(a and b) 返回 False |
- 成员运算符
除了以上的一些运算符之外,Python还支持成员运算符,测试实例中包含了一系列的成员,包括字符串,列表或元组。
运算符 | 描述 | 实例 |
---|---|---|
in | 如果在指定的序列中找到值返回 True,否则返回 False。 | x 在 y 序列中 , 如果 x 在 y 序列中返回 True。 |
not in | 如果在指定的序列中没有找到值返回 True,否则返回 False。 | x 不在 y 序列中 , 如果 x 不在 y 序列中返回 True。 |
-
身份运算符
身份运算符用于比较两个对象的存储单元
运算符 | 描述 | 实例 |
---|---|---|
is | is 是判断两个标识符是不是引用自一个对象 | x is y, 类似 id(x) == id(y) , 如果引用的是同一个对象则返回 True,否则返回 False |
is not | is not 是判断两个标识符是不是引用自不同对象 | x is not y , 类似 id(x) != id(y)。如果引用的不是同一个对象则返回结果 True,否则返回 False。 |
- 运算符优先级
以下表格列出了从最高到最低优先级的所有运算符, 相同单元格内的运算符具有相同优先级。 运算符均指二元运算,除非特别指出。 相同单元格内的运算符从左至右分组(除了幂运算是从右至左分组):
运算符 | 描述 |
---|---|
(expressions...) , [expressions...] , {key: value...} , {expressions...} | 圆括号的表达式 |
x[index] , x[index:index] , x(arguments...) , x.attribute | 读取,切片,调用,属性引用 |
await x | await 表达式 |
** | 乘方(指数) |
+x , -x , ~x | 正,负,按位非 NOT |
* , @ , / , // , % | 乘,矩阵乘,除,整除,取余 |
+ , - | 加和减 |
<< , >> | 移位 |
& | 按位与 AND |
^ | 按位异或 XOR |
` | ` |
in,not in, is,is not, <, <=, >, >=, !=, == | 比较运算,包括成员检测和标识号检测 |
not x | 逻辑非 NOT |
and | 逻辑与 AND |
or | 逻辑或 OR |
if -- else | 条件表达式 |
lambda | lambda 表达式 |
:= | 赋值表达式 |
2.3 基本数据类型
- 数据类型简介 type(a)
# 数字
a = 1
a = 1e2
a = 1 + 2j
# 字符串
a = "sinowealth"
a = "sino" + "wealth"
a = "sino" * 2
# 列表
a = list()
a = [1,"2",1+2j]
# 字典
a = dict()
a = {"name":"liming","age":"23"}
a["high"] = "175"
# 集合
a = set("abcd")
a = set([1,1,2,3])
a.add(4)
# 元组
a = ('Google', 'Runoob', 1997, 2000)
- 数据之间转换
函数 | 描述 |
---|---|
int(x) | 将x转换为一个整数 |
float(x) | 将x转换到一个浮点数 |
complex(real ,imag)] | 创建一个复数 |
str(x) | 将对象 x 转换为字符串 |
repr(x) | 将对象 x 转换为表达式字符串 |
eval(str) | 用来计算在字符串中的有效Python表达式,并返回一个对象 |
tuple(s) | 将序列 s 转换为一个元组 |
list(s) | 将序列 s 转换为一个列表 |
set(s) | 转换为可变集合 |
dict(d) | 创建一个字典。d 必须是一个 (key, value)元组序列。 |
frozenset(s) | 转换为不可变集合 |
chr(x) | 将一个整数转换为一个字符 |
ord(x) | 将一个字符转换为它的整数值 |
hex(x) | 将一个整数转换为一个十六进制字符串 |
oct(x) | 将一个整数转换为一个八进制字符串 |
2.4 条件及循环
- if判断语句:
# 判断
a = 1
if a is 1:
print("a is 1")
else:
print("a not is 1")
- while循环语句:
import time
while True:
print("pass")
time.sleep(1)
# continue
# return
else:
# 不符合进入此部分
print("fail")
- for循环语句:
for i in []:
print(i)
break
else:
print("ok")
pass
2.5 迭代器
# 迭代器
a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
a = (1, 2, 3, 4, 5, 6, 7, 8, 9)
a = {1, 2, 3, 4, 5, 6, 7, 8, 9}
# 创建迭代器
a_iter = iter(a)
# for i in range(len(a)):
# print(next(a_iter))
for i in a_iter:
print(i)
2.6 函数
# 函数
def max(a, b=1):
if a>b:
return a
elif a<b:
return b
else:
return a,b
print(max(1, 2))
print(max(5))
print(max(b = 3,a = 4))
2.7 堆栈概念
# 堆栈概念,先入后出,弹夹压子弹
a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 添加元素
a.append(10)
print(a)
# 弹出一个元素
a.pop()
print(a)
# 删除第一个元素
del a[0]
print(a)
2.8 模块
# 假设math文件里面定义了一个名为sin的函数,我们想使用sin函数可以有以下两种方式:
import math
print(math.sin(math.pi))
from math import sin,pi
print(sin(pi))
2.9 输入输出
import sys
# input()
print("haha")
# repr
out_str = "a = " + repr(1)
print(out_str)
# format
print("a = {0:d}".format(1))
print("a = {0:f}".format(1))
print("a = {}".format(1))
print("a = {0}, b = {1}, c = {0}".format(1, 2))
print('名字:{name}, 年龄:{age}'.format(name='李明', age='23'))
table = {'Google': 1, 'Runoob': 2, 'Taobao': 3}
print('Runoob: {Runoob:d}; Google: {Google:d}; Taobao: {Taobao:d}'.format(**table))
# %()匹配
print("a = %d"%(1))
# 将数字填充到需要的位数
a = "123"
print(a.zfill(5))
2.10 文件
【不同模式打开文件的完全列表】
模式 | r | r+ | w | w+ | a | a+ |
---|---|---|---|---|---|---|
读 | + | + | + | + | ||
写 | + | + | + | + | + | |
创建 | + | + | + | + | ||
覆盖 | + | + | ||||
指针在开始 | + | + | + | + | ||
指针在结尾 | + | + |
【文件操作常用函数】
序号 | 方法及描述 |
---|---|
1 | file.close()关闭文件。关闭后文件不能再进行读写操作。 |
2 | file.flush()刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入。 |
3 | file.fileno() 返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上。 |
4 | file.isatty()如果文件连接到一个终端设备返回 True,否则返回 False。 |
5 | file.next()**Python 3 中的 File 对象不支持 next() 方法。**返回文件下一行。 |
6 | [file.read(size])从文件读取指定的字节数,如果未给定或为负则读取所有。 |
7 | [file.readline(size])读取整行,包括 “\n” 字符。 |
8 | [file.readlines(sizeint])读取所有行并返回列表,若给定sizeint>0,返回总和大约为sizeint字节的行, 实际读取值可能比 sizeint 较大, 因为需要填充缓冲区。 |
9 | [file.seek(offset, whence])移动文件读取指针到指定位置 |
10 | file.tell()返回文件当前位置。 |
11 | [file.truncate(size])从文件的首行首字符开始截断,截断文件为 size 个字符,无 size 表示从当前位置截断;截断之后后面的所有字符被删除,其中 windows 系统下的换行代表2个字符大小。 |
12 | file.write(str)将字符串写入文件,返回的是写入的字符长度。 |
13 | file.writelines(sequence)向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符。 |
- 普通操作文件,需要手动关闭文件
# 创建一个文件
f = open('./test.txt', 'w', encoding='utf-8')
f.write( "Python 是一个非常好的语言。\n是的,的确非常好!!\n" )
f.close()
# 打开一个文件
f = open('./test.txt', 'r', encoding='utf-8')
# 设置光标切换到第四个字符后
f.seek(4)
# 查询光标位置
print(f.tell())
# 读取所有内容为一个字符串
str = f.read()
print(str)
# 读取15个字符
str = f.read(15)
print(str)
f.close()
with open(...) as ...
操作文件,不需要手动关闭文件
# 创建文件,写入数据
with open('./test.txt', 'w', encoding='utf-8') as f:
f.write('liming\n23')
# 打开文件,读取数据
with open('./test.txt', 'r', encoding='utf-8') as f:
# 一次读取多行为一个list
lines = f.readlines()
print(lines)
# 一行一行读取
# line = f.readline()
# print(lines)
# line = f.readline()
# print(lines)
2.11 OS模块
os 模块提供了非常丰富的方法用来处理文件和目录。常用的方法如下表所示:
序号 | 方法及描述 |
---|---|
1 | os.access(path, mode) 检验权限模式 |
2 | os.chdir(path) 改变当前工作目录 |
3 | os.chflags(path, flags) 设置路径的标记为数字标记。 |
4 | os.chmod(path, mode) 更改权限 |
5 | os.chown(path, uid, gid) 更改文件所有者 |
6 | os.chroot(path) 改变当前进程的根目录 |
7 | os.close(fd) 关闭文件描述符 fd |
8 | os.closerange(fd_low, fd_high) 关闭所有文件描述符,从 fd_low (包含) 到 fd_high (不包含), 错误会忽略 |
9 | os.dup(fd) 复制文件描述符 fd |
10 | os.dup2(fd, fd2) 将一个文件描述符 fd 复制到另一个 fd2 |
11 | os.fchdir(fd) 通过文件描述符改变当前工作目录 |
12 | os.fchmod(fd, mode) 改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限。 |
13 | os.fchown(fd, uid, gid) 修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定。 |
14 | os.fdatasync(fd) 强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息。 |
15 | [os.fdopen(fd, mode[, bufsize]]) 通过文件描述符 fd 创建一个文件对象,并返回这个文件对象 |
16 | os.fpathconf(fd, name) 返回一个打开的文件的系统配置信息。name为检索的系统配置的值,它也许是一个定义系统值的字符串,这些名字在很多标准中指定(POSIX.1, Unix 95, Unix 98, 和其它)。 |
17 | os.fstat(fd) 返回文件描述符fd的状态,像stat()。 |
18 | os.fstatvfs(fd) 返回包含文件描述符fd的文件的文件系统的信息,Python 3.3 相等于 statvfs()。 |
19 | os.fsync(fd) 强制将文件描述符为fd的文件写入硬盘。 |
20 | os.ftruncate(fd, length) 裁剪文件描述符fd对应的文件, 所以它最大不能超过文件大小。 |
21 | os.getcwd() 返回当前工作目录 |
22 | os.getcwdb() 返回一个当前工作目录的Unicode对象 |
23 | os.isatty(fd) 如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true, 否则False。 |
24 | os.lchflags(path, flags) 设置路径的标记为数字标记,类似 chflags(),但是没有软链接 |
25 | os.lchmod(path, mode) 修改连接文件权限 |
26 | os.lchown(path, uid, gid) 更改文件所有者,类似 chown,但是不追踪链接。 |
27 | os.link(src, dst) 创建硬链接,名为参数 dst,指向参数 src |
28 | os.listdir(path) 返回path指定的文件夹包含的文件或文件夹的名字的列表。 |
29 | os.lseek(fd, pos, how) 设置文件描述符 fd当前位置为pos, how方式修改: SEEK_SET 或者 0 设置从文件开始的计算的pos; SEEK_CUR或者 1 则从当前位置计算; os.SEEK_END或者2则从文件尾部开始. 在unix,Windows中有效 |
30 | os.lstat(path) 像stat(),但是没有软链接 |
31 | os.major(device) 从原始的设备号中提取设备major号码 (使用stat中的st_dev或者st_rdev field)。 |
32 | os.makedev(major, minor) 以major和minor设备号组成一个原始设备号 |
33 | [os.makedirs(path, mode]) 递归文件夹创建函数。像mkdir(), 但创建的所有intermediate-level文件夹需要包含子文件夹。 |
34 | os.minor(device) 从原始的设备号中提取设备minor号码 (使用stat中的st_dev或者st_rdev field )。 |
35 | [os.mkdir(path, mode]) 以数字mode的mode创建一个名为path的文件夹.默认的 mode 是 0777 (八进制)。 |
36 | [os.mkfifo(path, mode]) 创建命名管道,mode 为数字,默认为 0666 (八进制) |
37 | [os.mknod(filename, mode=0600, device]) 创建一个名为filename文件系统节点(文件,设备特别文件或者命名pipe)。 |
38 | [os.open(file, flags, mode]) 打开一个文件,并且设置需要的打开选项,mode参数是可选的 |
39 | os.openpty() 打开一个新的伪终端对。返回 pty 和 tty的文件描述符。 |
40 | os.pathconf(path, name) 返回相关文件的系统配置信息。 |
41 | os.pipe() 创建一个管道. 返回一对文件描述符(r, w) 分别为读和写 |
42 | [os.popen(command, mode[, bufsize]]) 从一个 command 打开一个管道 |
43 | os.read(fd, n) 从文件描述符 fd 中读取最多 n 个字节,返回包含读取字节的字符串,文件描述符 fd对应文件已达到结尾, 返回一个空字符串。 |
44 | os.readlink(path) 返回软链接所指向的文件 |
45 | os.remove(path) 删除路径为path的文件。如果path 是一个文件夹,将抛出OSError; 查看下面的rmdir()删除一个 directory。 |
46 | os.removedirs(path) 递归删除目录。 |
47 | os.rename(src, dst) 重命名文件或目录,从 src 到 dst |
48 | os.renames(old, new) 递归地对目录进行更名,也可以对文件进行更名。 |
49 | os.rmdir(path) 删除path指定的空目录,如果目录非空,则抛出一个OSError异常。 |
50 | os.stat(path) 获取path指定的路径的信息,功能等同于C API中的stat()系统调用。 |
51 | [os.stat_float_times(newvalue]) 决定stat_result是否以float对象显示时间戳 |
52 | os.statvfs(path) 获取指定路径的文件系统统计信息 |
53 | os.symlink(src, dst) 创建一个软链接 |
54 | os.tcgetpgrp(fd) 返回与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组 |
55 | os.tcsetpgrp(fd, pg) 设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg。 |
56 | os.tempnam([dir[, prefix]]) **Python3 中已删除。**返回唯一的路径名用于创建临时文件。 |
57 | os.tmpfile() **Python3 中已删除。**返回一个打开的模式为(w+b)的文件对象 .这文件对象没有文件夹入口,没有文件描述符,将会自动删除。 |
58 | os.tmpnam() **Python3 中已删除。**为创建一个临时文件返回一个唯一的路径 |
59 | os.ttyname(fd) 返回一个字符串,它表示与文件描述符fd 关联的终端设备。如果fd 没有与终端设备关联,则引发一个异常。 |
60 | os.unlink(path) 删除文件路径 |
61 | os.utime(path, times) 返回指定的path文件的访问和修改的时间。 |
62 | [os.walk(top, topdown=True[, οnerrοr=None[, followlinks=False]]]) 输出在文件夹中的文件名通过在树中游走,向上或者向下。 |
63 | os.write(fd, str) 写入字符串到文件描述符 fd中. 返回实际写入的字符串长度 |
64 | os.path 模块 获取文件的属性信息。 |
65 | os.pardir() 获取当前目录的父目录,以字符串形式显示目录名。 |
os.path 模块主要用于获取文件的属性。
方法 | 说明 |
---|---|
os.path.abspath(path) | 返回绝对路径 |
os.path.basename(path) | 返回文件名 |
os.path.commonprefix(list) | 返回list(多个路径)中,所有path共有的最长的路径 |
os.path.dirname(path) | 返回文件路径 |
os.path.exists(path) | 路径存在则返回True,路径损坏返回False |
os.path.lexists | 路径存在则返回True,路径损坏也返回True |
os.path.expanduser(path) | 把path中包含的""和"user"转换成用户目录 |
os.path.expandvars(path) | 根据环境变量的值替换path中包含的" n a m e " 和 " name"和" name"和"{name}" |
os.path.getatime(path) | 返回最近访问时间(浮点型秒数) |
os.path.getmtime(path) | 返回最近文件修改时间 |
os.path.getctime(path) | 返回文件 path 创建时间 |
os.path.getsize(path) | 返回文件大小,如果文件不存在就返回错误 |
os.path.isabs(path) | 判断是否为绝对路径 |
os.path.isfile(path) | 判断路径是否为文件 |
os.path.isdir(path) | 判断路径是否为目录 |
os.path.islink(path) | 判断路径是否为链接 |
os.path.ismount(path) | 判断路径是否为挂载点 |
os.path.join(path1[, path2[, …]]) | 把目录和文件名合成一个路径 |
os.path.normcase(path) | 转换path的大小写和斜杠 |
os.path.normpath(path) | 规范path字符串形式 |
os.path.realpath(path) | 返回path的真实路径 |
os.path.relpath(path[, start]) | 从start开始计算相对路径 |
os.path.samefile(path1, path2) | 判断目录或文件是否相同 |
os.path.sameopenfile(fp1, fp2) | 判断fp1和fp2是否指向同一文件 |
os.path.samestat(stat1, stat2) | 判断stat tuple stat1和stat2是否指向同一个文件 |
os.path.split(path) | 把路径分割成 dirname 和 basename,返回一个元组 |
os.path.splitdrive(path) | 一般用在 windows 下,返回驱动器名和路径组成的元组 |
os.path.splitext(path) | 分割路径中的文件名与拓展名 |
os.path.splitunc(path) | 把路径分割为加载点与文件 |
os.path.walk(path, visit, arg) | 遍历path,进入每个目录都调用visit函数,visit函数必须有3个参数(arg, dirname, names),dirname表示当前目录的目录名,names代表当前目录下的所有文件名,args则为walk的第三个参数 |
os.path.supports_unicode_filenames | 设置是否支持unicode路径名 |
- 举个栗子
# os模块
# 调用系统相关功能
import os, sys, stat
# 本文件路径
# print("本文件路径:", __file__)
# 切换到本文件所在目录
dir_name = os.path.dirname(__file__)
# print("本文件所在目录:", dir_name)
file_name = os.path.basename(__file__)
# print("本文件名:", file_name)
# # 列出当前目录下文件
# print(os.listdir('./') )
# 切换到本文件所在目录
os.chdir(dir_name)
# # 列出当前目录下文件
# print(os.listdir('./') )
# # 返回父目录,即".."
# print(os.pardir)
# print("父目录", os.path.join("C:/Users/a1235/Desktop/TE-python培训/脚本", os.pardir))
# # 返回绝对路径
# print("绝对路径:", os.path.abspath("./"))
# # 公共路径
# path_list = list()
# path_list.append("C:/Users/a1235/Desktop/TE-python培训/脚本")
# path_list.append("C:/Users/a1235/Desktop/xxx")
# print("公共路径为:", os.path.commonpath(path_list))
# # 判断目录是否存在
# if os.path.exists(os.path.dirname(__file__)):
# print("os.path.dirname(__file__) 目录存在")
# else:
# print("os.path.dirname(__file__) 目录不存在")
# # 获取文件最后的访问时间(时间戳)
# print("文件 %s 最后访问时间为 %s"%(__file__, os.path.getatime(__file__)))
# # 获取文件最后的修改时间(时间戳)
# print("文件 %s 最后修改时间为 %s"%(__file__, os.path.getmtime(__file__)))
# # 获取文件创建时间(时间戳)
# print("文件 %s 创建时间 %s"%(__file__, os.path.getctime(__file__)))
# import time
# timeArray = time.localtime(os.path.getctime(__file__))
# print(time.strftime("%Y-%m-%d %H:%M:%S", timeArray))
# # 获取文件大小
# print("文件 %s 大小为 %s bit"%(__file__, os.path.getsize(__file__)))
# # 判断目录是否为绝对目录
# # if os.path.isabs("./"):
# if os.path.isabs("C:/Users/a1235/Desktop/"):
# print("是绝对目录")
# else:
# print("不是绝对目录")
# # 判断path是目录还是文件
# path = "C:/Users/a1235/Desktop/TE-python培训/脚本/python培训.py"
# if os.path.isdir(path):
# print("is dir")
# elif os.path.isfile(path):
# print("is file")
# else:
# print("is not any")
# # 返回真实路径
# print(os.path.realpath("./"))
# # 分割路径
# dir_name, file_name = os.path.split(__file__)
# print("dir : %s, file : %s"%(dir_name, file_name))
# # 分割文件名与后缀
# file_name, index_name = os.path.splitext(__file__)
# print("file : %s, index : %s"%(file_name, index_name))
# 切换到指定目录
os.chdir("C:\\Users\\a1235\\Desktop\\TE-python培训\\脚本")
os.chdir("C:/Users/a1235/Desktop/TE-python培训/脚本")
# # 路径拼接
# dir_name = "C:\\Users\\a1235\\Desktop\\TE-python培训\\脚本"
# dir_name = "C:/Users/a1235/Desktop/TE-python培训/脚本"
# file_name = "python培训.py"
# print(dir_name + file_name)
# print(dir_name + "/" + file_name)
# print(os.path.join(dir_name, file_name))
# # 测试当前目录是否存在
# test_path = "C:/Users/a1235/Desktop/TE-python培训/脚本"
# # test_path = os.path.join(test_path, "python培训.py")
# test_path = os.path.join(test_path, "python培.py")
# ret = os.access(test_path, os.F_OK)
# print ("python培训.py 文件存在嘛? %s"% ret)
# # 改变文件权限
# test_path = "C:/Users/a1235/Desktop/TE-python培训/脚本/moudle.py"
# # 其他用户有全部权限(权限掩码)0o007
# os.chmod(test_path, stat.S_IRWXO)
# 查询当前文件工作目录
print(os.getcwd())
os.chdir("..")
print(os.getcwd())
# 创建一个名为"new_dir1/new_dir2"的目录
if not os.path.exists("new_dir1/new_dir2"):
os.makedirs("new_dir1/new_dir2")
# os.mkdir("new_dir1/new_dir2")
# os.makedirs("new_dir1/new_dir2", 0o777)
# os.mkdir("new_dir1/new_dir2", 0o777)
pass
# 用os打开文件
f = os.open('./test.txt', os.O_RDWR|os.O_CREAT)
# 读文件
print(os.read(f, 3))
# 写入字符串,此时光标已经移到第3位
os.write(f, str.encode(" hello "))
# 关闭文件
os.close(f)
# 重命名文件
if os.path.exists("./test1.txt"):
os.remove("./test1.txt")
os.rename('./test.txt', './test1.txt')
# # 重命名目录
# os.rename("new_dir1/new_dir2", "new_dir1/new_dir")
# os.rename("new_dir1/new_dir", "new_dir1/new_dir2")
# 递归重命名
os.renames("new_dir1/new_dir2", "new_dir/new_dir")
os.renames("new_dir/new_dir", "new_dir1/new_dir2")
# 删除文件
os.remove("./test1.txt")
# 删除目录
# os.rmdir("new_dir1/new_dir2")
# # 递归删除目录,"new_dir1/new_dir2"都会删除,需谨慎
# os.removedirs("new_dir1/new_dir2")
# # 列出当前目录下文件
# print(os.listdir('./') )
# # 输出在文件夹中的文件名通过在树中游走,向上或者向下。
# for root, dirs, files in os.walk("C:/Users/a1235/Desktop/TE-python培训"):
# print("root is ", root)
# print("dir is ", dirs)
# for f in files:
# if f.endswith(".bsdl"):
# print(f)
# print(os.path.join(root, f))
# pass
# # 调用终端来执行命令
# os.chdir(os.path.dirname(__file__))
# exit_py_file_name = "moudle.py"
# os.system("python3 %s"%(exit_py_file_name))
2.12 错误和异常
# 错误和异常
try:
a = 3/0
print("除法成功!")
print(a)
except:
print("除法失败!")
pass
print("succeeded!")
# 尝试导入库
try:
import matplotlib
except:
import os
os.system("pip3 install matplotlib")
import matplotlib
else:
print(matplotlib.__path__)
finally:
print("我很牛,我不管怎样都会执行!")
try:
a = 3/0
except:
pass
else:
b = 3/1
finally:
print("我很牛,我不管怎样都会执行!")
2.13 面向对象
你想吃鱼香肉丝,你有两种选择:
1.切肉丝、切青椒丝、切胡萝卜、配酱料、炒熟。
2.冲进饭店喊一句:服务员,点一盘鱼香肉丝。
前者自己操作所有材料,控制加工流程。这就是面向过程。后者,命令一个对象去解决问题,这就是面向对象。
而事实证明面向对象往往更符合人类的思维方式。
# 面向过程
def talk(name,content):
print('%s : %s'%(name,content))
talk('岳云鹏','大家好,我是岳云鹏')
talk('孙越','是了')
talk('岳云鹏','这位是我的师猪,孙越老师')
talk('孙越','我呀?')
# 面向对象
class comedian():
def __init__(self,name):
self.name=name
def talk(self,content):
print('%s : %s'%(self.name,content))
p1=comedian('岳云鹏')
p2=comedian('孙越')
p1.talk('大家好,我是岳云鹏')
p2.talk('是了')
p1.talk('这位是我的师猪,孙越老师')
p2.talk('我呀?')
2.14 命名空间
一般有三种命名空间:
- 内置名称(built-in names), Python 语言内置的名称,比如函数名 abs、char 和异常名称 BaseException、Exception 等等。
- 全局名称(global names),模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
- 局部名称(local names),函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量。(类中定义的也是)
# var1 是全局名称
var1 = 5
def some_func():
# var2 是局部名称
var2 = 6
def some_inner_func():
# var3 是内嵌的局部名称
var3 = 7
Python 的作用域一共有4种,分别是:
有四种作用域:
- L(Local):最内层,包含局部变量,比如一个函数/方法内部。
- E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
- G(Global):当前脚本的最外层,比如当前模块的全局变量。
- B(Built-in): 包含了内建的变量/关键字等,最后被搜索。
规则顺序: L –> E –> G –> B。
在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。
# 命名空间
a = 1
if 1:
a = 3
print(a)
def rename_a():
a = 2
rename_a()
print(a)
# global 和 nonlocal关键字
num = 1
print(num)
def outer():
num = 2
def inner():
nonlocal num # nonlocal关键字声明
# global num # global关键字声明
num = 3
print(num)
inner()
print(num)
outer()
print(num)
# class中的命名空间
class Test():
a = 10
def __init__(self):
# global a
# self.b = a
self.b = self.a
# self.b = Test.a
print(self.b)
test1 = Test()
test2 = Test()
test3 = Test()
2.15 常用函数
举例:
# 文件通配符,返回工作目录下所有.py文件
import glob
print(glob.glob('./脚本/*.py'))
# 打印本文件定义的变量、函数及引用的资源等等
print(dir())
print(dir(glob))
def test_xxx():
b = 10
c = 2000
print(dir())
test_xxx()
# 命令行参数
import sys
print(sys.argv)
⭐️3. 正则表达式
3.1 简介及资源
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配,或者帮你找出符合你要求的字符串格式片段。
3.2 匹配时可选填参数
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
3.3 测试代码举例
# 正则表达式
import re
test_str = "hahahahaha test_no(00) wdededed TEST_NO(1)"
# 从起始位置匹配
print(re.match("test_no\(\d+\)", test_str))
print(re.match("ha\w+", test_str))
print(re.match("ha\w+", test_str).group())
# 从任意位置匹配
print(re.search("test_no\(\d+\)", test_str))
print(re.search("test_no\(\d+\)", test_str, re.I).group())
# 找到所有匹配的对象
print(re.findall("test_no\(\d+\)", test_str, re.I))
# 用迭代器查询所有匹配的对象
print(re.finditer("test_no\(\d+\)", test_str, re.I))
for iter in re.finditer("test_no\(\d+\)", test_str, re.I):
print(iter.group())
# 替换
print(re.sub("test_no\(\d+\)", "test_no(10)", test_str, count = 2, flags = re.I))
# 将匹配的数字乘于 2
def double(matched):
value = int(matched.group('value'))
return str(value * 2)
s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))
# 也可以提取其中的参数
pattern = re.compile("test_no\(\d+\)") # 查找数字
pattern = re.compile("test_no\((\d+)\)") # 查找数字
print(pattern.findall("hahahahaha test_no(0) wdededed test_no(1)"))
result = re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')
print(result)
# 用正则分割
print(re.split("test_no\(\d+\)", test_str, flags = re.I))
# 用空格分割
print(re.split("\s+", test_str))
3.4 基础正则表达式速查表
- 字符
表达式 | 描述 |
---|---|
[abc] | 字符集。匹配集合中所含的任一字符。 |
[^abc] | 否定字符集。匹配任何不在集合中的字符。 |
[a-z] | 字符范围。匹配指定范围内的任意字符。 |
. | 匹配除换行符以外的任何单个字符。 |
\ | 转义字符。 |
\w | 匹配任何字母数字,包括下划线(等价于 [A-Za-z0-9_] )。 |
\W | 匹配任何非字母数字(等价于 [^A-Za-z0-9_] )。 |
\d | 数字。匹配任何数字。 |
\D | 非数字。匹配任何非数字字符。 |
\s | 空白。匹配任何空白字符,包括空格、制表符等。 |
\S | 非空白。匹配任何非空白字符。 |
- 分组和引用
表达式 | 描述 |
---|---|
(expression) | 分组。匹配括号里的整个表达式。 |
(?:expression) | 非捕获分组。匹配括号里的整个字符串但不获取匹配结果,拿不到分组引用。 |
\num | 对前面所匹配分组的引用。比如 (\d)\1 可以匹配两个相同的数字,(Code)(Sheep)\1\2 则可以匹配 CodeSheepCodeSheep 。 |
- 锚点/边界
表达式 | 描述 |
---|---|
^ | 匹配字符串或行开头。 |
$ | 匹配字符串或行结尾。 |
\b | 匹配单词边界。比如 Sheep\b 可以匹配 CodeSheep 末尾的 Sheep ,不能匹配 CodeSheepCode 中的 Sheep |
\B | 匹配非单词边界。比如 Code\B 可以匹配 HelloCodeSheep 中的 Code ,不能匹配 HelloCode 中的 Code 。 |
- 数量表示
表达式 | 描述 |
---|---|
? | 匹配前面的表达式0个或1个。即表示可选项。 |
+ | 匹配前面的表达式至少1个。 |
* | 匹配前面的表达式0个或多个。 |
` | ` |
{m} | 匹配前面的表达式m个。 |
{m,} | 匹配前面的表达式最少m个。 |
{m,n} | 匹配前面的表达式最少m个,最多n个。 |
- 预查断言
表达式 | 描述 |
---|---|
(?=) | 正向预查。比如 Code(?=Sheep) 能匹配 CodeSheep 中的 Code ,但不能匹配 CodePig 中的 Code 。 |
(?!) | 正向否定预查。比如 Code(?!Sheep) 不能匹配 CodeSheep 中的 Code ,但能匹配 CodePig 中的 Code 。 |
(?<=) | 反向预查。比如 (?<=Code)Sheep 能匹配 CodeSheep 中的 Sheep ,但不能匹配 ReadSheep 中的 Sheep 。 |
(?<!) | 反向否定预查。比如 (?<!Code)Sheep 不能匹配 CodeSheep 中的 Sheep ,但能匹配 ReadSheep 中的 Sheep 。 |
- 特殊标志
表达式 | 描述 |
---|---|
/.../i | 忽略大小写。 |
/.../g | 全局匹配。 |
/.../m | 多行修饰符。用于多行匹配。 |
⭐️4. JSON 数据解析
4.1 简介
C、Python、C++、Java、PHP、Go、HTML等编程语言都支持 JSON。JSON数据格式如下:
{
"name": "sinowealth",
"flag": 1,
"people": [
{
"name": "liming",
"age": 18
},
{
"name": "xiaohong",
"age": 17,
"high": 168
}
]
}
4.2 Python 编码为 JSON 类型转换对应表:
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float, int- & float-derived Enums | number |
True | true |
False | false |
None | null |
4.3 举例如下
# Json数据
import json
dict_object = dict()
# 添加元素
dict_object["name"] = "sinowealth"
dict_object["flag"] = 1
dict_object["people"] = list()
print(dict_object)
# peoples = list()
people = dict()
people["name"] = "liming"
people["age"] = 18
print(people)
dict_object["people"].append(people)
print(dict_object)
people = dict()
people["name"] = "xiaohong"
people["age"] = 17
people["high"] = 168
print(people)
dict_object["people"].append(people)
print(dict_object)
# Python 字典类型转换为 JSON 对象
json_object = json.dumps(dict_object)
print(json_object)
# 将 JSON 对象转换为 Python 字典
dict_object = json.loads(json_object)
print(dict_object)
print(dict_object["name"])
# 写入JSON数据
with open('data.json', 'w', encoding = 'utf-8') as f:
json.dump(dict_object, f, indent=4)
# 读取数据
with open('data.json', 'r', encoding = 'utf-8') as f:
dict_object = json.load(f)
print(dict_object)
print(dict_object["name"])
list_a = list()
people = dict()
people["name"] = "liming"
people["age"] = 18
list_a.append(people)
people["name"] = "xiaohong"
print(list_a)
⭐️5. python3代码规范
5.1 文件编码
如无特殊情况,文件一律使用utf-8编码,即在文件头部必须加入标识:# -*- conding: utf-8 -*-
。
5.2 代码格式
- 缩进
统一使用4个空格进行缩进,不要使用 TAB
进行缩进,各个软件的 TAB
定义不一样
- 行宽
每行代码尽量不要超过 80 个字符(在特殊情况下,可以略微超过 80,但最长不能超过 120 个字符)。
- 自然语言使用双引号,机器标示使用单引号。因此,在多数情况下,代码里应该是使用单引号。
- 自然语言使用双引号:例如错误信息等。
- 机器标示使用单引号:例如 dict 中的 key。
- 正则表达式使用原生的双引号:r""。
- 文档字符串(docstring)使用三个双引号。
- 空行
- 模块级函数和类定义之间空两行。
- 类的成员函数之间空一行。
- 使用多个空行分割多组相关的函数。
- 函数中使用空行分割逻辑相关的代码。
5.3 import 语句
import
语句应该分行书写
# 正确的写法
import os
import sys
# 不推荐的写法
import os, sys
# 正确的写法
from subprocess import Popen, PIPE
import
语句应该使用absolute import
# 正确的写法
from foo.bar import Bar
# 不推荐的写法
from ..bar import Bar
import
语句应该放在文件头部,置于模块说明及docstring
之后,于全局变量之前import
语句应该按照顺序排列,每组之间用一个空行分隔
import os
import sys
import msgpack
import zmq
import foo
- 导入其他模块的类定义时,可以使用相对导入
from myclass import MyClass
- 如果发生命名冲突,则可使用命名空间
import bar
import foo.bar
bar.Bar()
foo.bar.Bar()
- 导入其他模块的类定义时,可以使用相对导入
from myclass import MyClass
5.4 空格
- 在二元运算符两边各空一格
[=,-,+=,==,>,in,is not, and]
:
# 正确的写法
i = i + 1
submitted += 1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
# 不推荐的写法
i=i+1
submitted +=1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
- 在一元前缀运算符后不加空格,以"!"为例:
if !flag:
pass
“:”
用在行尾时,前后皆不加空格,如分枝、循环、函数和类定义语言。
# 正确的写法
def complex(real, imag):
pass
# 不推荐的写法
def complex(real,imag):
pass
- 函数的参数列表中,
","
之后要有空格。
# 正确的写法
def complex(real, imag):
pass
# 不推荐的写法
def complex(real,imag):
pass
- 函数的参数列表中,默认值等号两边不要添加空格。
# 正确的写法
def complex(real, imag=0.0):
pass
# 不推荐的写法
def complex(real, imag = 0.0):
pass
- 括号(含圆括号、方括号和花括号)前后不加空格。
# 正确的写法
spam(ham[1], {eggs : 2})
# 不推荐的写法
spam( ham[1], { eggs : 2 } )
- 字典对象的左括号之前,不要多余的空格。
# 正确的写法
dict['key'] = list[index]
# 不推荐的写法
dict ['key'] = list [index]
- 不要为对齐赋值语句而使用的额外空格。
# 正确的写法
x = 1
y = 2
long_variable = 3
# 不推荐的写法
x = 1
y = 2
long_variable = 3
5.5 换行
- Python3 支持括号内的换行
# 第二行缩进到括号的起始处
foo = long_function_name(var_one, var_two,
var_three, var_four)
# 第二行缩进 4 个空格,适用于起始括号就换行的情形
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
- 使用反斜杠
换行、二元运算符+.
等应出现在行末;长字符串也可以用此法换行
session.query(MyTable).\
filter_by(id=1).\
one()
print 'Hello, '\
'%s %s!' %\
('Harry', 'Potter')
- 禁止复合语句,即一行中包含多个语句:
# 正确的写法
do_first()
do_second()
do_third()
# 不推荐的写法
do_first();do_second();do_third();
if/for/while
一定要换行:
# 正确的写法
if foo == 'blah':
do_blah_thing()
# 不推荐的写法
if foo == 'blah': do_blash_thing()
5.6 docstring文档字符串
- 鼠标放在函数定义上面会显示该函数的docstring ,docstring 的规范中最其本的两点:
- 所有的公共模块、函数、类、方法,都应该写 docstring 。私有方法不一定需要,但应该在 def 后提供一个块注释来说明。
- docstring 的结束"""应该独占一行,除非此 docstring 只有一行。
"""Return a foobar
Optional plotz says to frobnicate the bizbaz first.
"""
"""Oneline docstring"""
5.7 注释
- 块注释,“#”号后空一格,段落之间用空行分开(同样需要“#”号)
# 块注释
# 块注释
#
# 块注释
# 块注释
- 行注释,至少使用两个空格和语句分开,注意不要使用无意义的注释
# 正确的写法
x = x + 1 # 边框加粗一个像素
# 不推荐的写法(无意义的注释)
x = x + 1 # x加1
- 文档注释
作为文档注释的Docstring,一般出现在模块头部、函数和类的头部。在python3中,这样可以通过对象的__doc__对象获取文档。 编辑器和IDE也可以根据Docstring给出自动提示。文档注释以 “”" 开头和结尾,首行不换行。如有多行,末行必需换行,以下是Google的docstring风格示例:
# -*- coding: utf-8 -*-
"""Example docstrings.
This module demonstrates documentation as specified by the `Google Python
Style Guide`_. Docstrings may extend over multiple lines. Sections are created
with a section header and a colon followed by a block of indented text.
Example:
Examples can be given using either the ``Example`` or ``Examples``
sections. Sections support any reStructuredText formatting, including
literal blocks::
$ python example_google.py
Section breaks are created by resuming unindented text. Section breaks
are also implicitly created anytime a new section starts.
"""
- 不要在文档注释中复制函数定义原型,而是描述其具体内容,包括参数和返回值等。
# 不推荐的写法(不要写函数原型等废话)
def function(a, b):
"""function(a, b) -> list"""
... ...
# 正确的写法
def function(a, b):
"""计算并返回a到b范围内数据的平均值"""
... ...
- 对函数参数、返回值等的说明采用
numpy
标准, 如下所示:
文档注释不限于中英文, 但不要中英文混用。
文档注释不是越长越好, 通常一两句话能把情况说清楚即可。
模块、公有类、公有方法, 能写文档注释的, 应该尽量写文档注释。
添加注释的原则:坚持适当注释原则。
对不存在技术难点的代码不注释,对存在技术难点的代码必须注释。但与注释不同,建议对每一个包、模块、类、函数(方法)写 docstrings,除非代码一目了然,非常简单。
def func(arg1, arg2):
"""在这里写函数的一句话总结(如: 计算平均值)。
这里是具体描述.
参数
----------
arg1 : int
arg1的具体描述。
arg2 : int
arg2的具体描述。
返回值
-------
int
返回值的具体描述。
参看
--------
otherfunc : 其它关联函数等...
示例
--------
示例使用doctest格式。在`>>>`后的代码,可以被文档测试工具作为测试用例自动运行。
>>> a=[1,2,3]
>>> print [x + 3 for x in a]
[4, 5, 6]
"""
pass
5.8 命名规范
- 模块
模块尽量使用小写命名,首字母保持小写,尽量不要用下划线(除非多个单词,且数量不多的情况)。
# 正确的模块名
import decoder
import html_parser
# 不推荐的模块名
import Decoder
- 类名
类名使用驼峰(CamelCase
)命名风格,首字母大写,私有类可用一个下划线开头。
将相关的类和顶级函数放在同一个模块里。
class Farm():
pass
class AnimalFarm(Farm):
pass
class _PrivateFarm(Farm):
pass
- 函数
函数名一律小写,如有多个单词,用下划线隔开。
def run():
pass
def run_with_env():
pass
- 变量名
变量名尽量小写, 如有多个单词,用下划线隔开。
if __name__ == '__main__':
count = 0
school_name = ''
常量采用全大写,如有多个单词,使用下划线隔开
MAX_CLIENT = 100
MAX_CONNECTION = 1000
CONNECTION_TIMEOUT = 600
- 包名
包命名尽量短小,使用全部小写的方式**,不可以使用下划线**。
⭐️6. openpyxl库
安装库:pip install openpyxl
6.1 简介
整个openpyxl库总共包含:
workbook
: 工作薄
sheet
: 工作表
cell
: 单元格
6.2 读表格
import os, sys, time, re
from openpyxl import load_workbook
from openpyxl.cell import MergedCell
from openpyxl.worksheet.worksheet import Worksheet
os.chdir(os.path.dirname(__file__))
# 读取表格操作
# 打开表格
wb = load_workbook("MP test script.xlsx")
# 打印所有sheet名
print(wb.sheetnames)
# for sheet in wb:
# print(sheet.title)
# 打开第2个sheet
ws = wb[wb.sheetnames[1]]
# 获取普通或者合并单元格的内容
def get_merged_cell(sheet:Worksheet, row, col):
"""
获取普通或者合并单元格的内容\n
sheet名,行,列
"""
try:
cell = sheet.cell(row = row, column = col)
if isinstance(cell, MergedCell):
for merged_range in sheet.merged_cells.ranges:
if cell.coordinate in merged_range:
cell = sheet.cell(row = merged_range.min_row, column = merged_range.min_col)
break
return cell.value
except:
return ""
# 直接通过标签进行访问
print(ws.cell(row=7, column=2).value)
# 直接通过标签进行访问
print(ws["B7"].value)
# 查询合并单元格元素值
print(get_merged_cell(ws, 8, 2))
# 通过标签框选一部分ws['B3':'C4']进行读取
print(ws['B3':'C4'][0][0].value)
# 通过列ws['B']进行读取
print(ws['B'][2].value)
# 通过列范围ws['B:C']进行读取
print(ws['B':'C'][0][2].value)
# 通过行ws[3]进行读取
print(ws[3][1].value)
# 通过行范围ws[3:4]进行读取
print(ws[3:4][0][1].value)
# sheet最大最小行
print("max_row:", ws.max_row)
print("min_row:", ws.min_row)
# sheet最大最小列
print("max_col:", ws.max_column)
print("min_col:", ws.min_column)
# 打印sheet内的元素
for row in range(ws.min_row, ws.max_row + 1): # 向下
for col in range(ws.min_column, ws.max_column + 1): # 向右
# print(get_merged_cell(ws, 7, 2))
pass
# 按行读取
for row in ws.rows:
for cell in row:
# print(cell.value)
pass
# 按列读取
for column in ws.columns:
for cell in column:
# print(cell.value)
pass
# 通过指定范围,返回结果为(行 → 行)
for row in ws.iter_rows(min_row=3, max_row=4, min_col=2, max_col=3):
for cell in row:
# print(cell.value)
pass
# 通过指定范围,返回结果为(列 → 列)
for col in ws.iter_cols(min_row=3, max_row=4, min_col=2, max_col=3):
for cell in col:
# print(cell.value)
pass
from openpyxl.utils import get_column_letter, column_index_from_string
# 根据列的数字返回字母
print(get_column_letter(2)) # B
# 根据字母返回列的数字
print(column_index_from_string('D')) # 4
6.3 写表格
# 写表格
import os, sys, time, re
from openpyxl import load_workbook
from openpyxl.cell import MergedCell
from openpyxl.worksheet.worksheet import Worksheet
from openpyxl import Workbook
os.chdir(os.path.dirname(__file__))
# 创建表格
# 实例化
wb = Workbook()
# 激活sheet0
ws0 = wb.active
# 设置sheet名称
ws0.title = "test0"
# 查询sheet名称
print(ws0.title)
# 创建sheet1
ws1 = wb.create_sheet("test1", 0)
# 创建sheet2
ws2 = wb.create_sheet("test2", 1)
# 打印目前sheet
print(wb.sheetnames)
# 删除sheet
wb.remove(ws2)
# del wb["test2"]
# 打印目前sheet
print(wb.sheetnames)
# 通过sheet名选择sheet
print(wb.get_sheet_by_name("test0")) # 已丢弃,不建议使用
print(wb["test0"])
print(ws0)
# 保存表格
wb.save("new_excel_test.xlsx")
# 给表格赋值
# 方式一:通过标签
ws1['A1'] = 42
# 方式二:可以附加行,从第一列开始附加(从最下方空白处,最左开始)(可以输入多行)
ws1.append([1, 2, 3])
ws1.append([4, 5, 6])
# 方式三:通过坐标值
ws1.cell(row=4, column=1).value = "sino1"
ws1.cell(row=5, column=1, value="sino2")
# 保存表格
wb.save("new_excel_test.xlsx")
6.4 主题
# 主题操作
import os, sys, time, re
from openpyxl import load_workbook, Workbook
from openpyxl.cell import MergedCell
from openpyxl.worksheet.worksheet import Worksheet
from openpyxl.utils import get_column_letter, column_index_from_string
from openpyxl.styles import Border, Side, PatternFill, Font, colors, GradientFill, Alignment
os.chdir(os.path.dirname(__file__))
# 创建表格
# 实例化
wb = Workbook()
# 激活sheet0
ws0 = wb.active
# 给表格赋值
for row in range(1, 20):
for column in range(1, 6):
ws0.cell(row=row, column=column).value = ("%d x %d"%(row, column))
# 第1行行高
ws0.row_dimensions[1].height = 40
# A列列宽
ws0.column_dimensions['A'].width = 30
# ws0.column_dimensions[get_column_letter(1)].width = 30
# 设置单元格数据水平和竖直方向对齐方式,除了center,还可以使用 right、left等等参数。
ws0.cell(row=1, column=1).alignment = Alignment(horizontal='center', vertical='center')
# 设置自动换行
ws0.cell(row=1, column=1).alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)
# 设置字体|大小|颜色|加粗
ws0.cell(row=1, column=1).font = Font(name='微软雅黑', size=10, color="00FF00", bold=True)
# 设置单元格边框
ws0.cell(row=1, column=1).border = Border(top = Side(border_style='thin', color='FF000000'),
right = Side(border_style='thin', color='FF000000'),
bottom = Side(border_style='thin', color='FF000000'),
left = Side(border_style='thin', color='FF000000'))
# 设置背景颜色(24bit RGB)
ws0.cell(row=1, column=1).fill = PatternFill(fill_type='solid', start_color="DA9694")
# 合并单元格, 往左上角写入数据即可
ws0.merge_cells('A1:B2') # 合并一行中的几个单元格
ws0.merge_cells(start_row=5, end_row=6, start_column=3, end_column=4) # 合并一行中的几个单元格
# 拆分合并单元格,取消合并单元格
ws0.unmerge_cells('C5:D6') # 合并一行中的几个单元格
# ws0.unmerge_cells(start_row=5, end_row=6, start_column=3, end_column=4)
# 保存表格
wb.save("new_excel_test.xlsx")