网站后台管理系统 asp,网站的优点有哪些,郑州哪个妇科医院检查比较好,网站建设三大部分基础语法
字面量
什么是字面量#xff1a; 在代码中#xff0c;被写下来的固定的值#xff0c;称为字面量 | 类型 | 描述 | 说明 | | — | — | — | | 数组#xff08;Number#xff09; | 整数 int | 整数 | | | 浮点型 float | 浮点数 | | | 复数 complex | 复数 如 …基础语法
字面量
什么是字面量 在代码中被写下来的固定的值称为字面量 | 类型 | 描述 | 说明 | | — | — | — | | 数组Number | 整数 int | 整数 | | | 浮点型 float | 浮点数 | | | 复数 complex | 复数 如 43j 以j结尾标识复数 | | | 布尔 | True Flase 1 0 | | 字符串 String | 描述文本的一种数据类型 | 又称文本由任意数量的字符如中文英文各类符号数字等组成。Python中字符串需要用双引号包围起来被引号包围的都是字符串 | | 列表 List | 有序的可变序列 | Python中使用最频繁的数据类型可有序记录一堆数据 | | 元组 Tuple | 有序的不可变序列 | 有序记录一堆不可变的Python数据集合 | | 集合 Set | 无序不重复集合 | 可无序记录一堆不重复的Python数据集合 | | 字典 Dictionary | 无序Key-Value集合 | 可无序记录一堆Key-Value型的Python数据集合 |
注释
单行注释以#开头#右边的所有文字当做说明而不是真正要执行的程序起辅助作用注意#号和注释内容建议以一个空格隔开。多行注释以一对三个双引号引起来“” 注释内容支持换行“”来解释说明一段代码的作用的使用方法。
变量
在程序运行时能存储计算结果或者能表示值的抽象概念变量定义格式 变量名称 变量值 每一个变量都有自己的名称称之为变量名也就是变量本身赋值表示将等号右侧的值赋予左侧的值每一个变量都有自己存储的值称之为变量值
数据类型
可以使用type() 查看变量类型 通过type(变量)是查看变量的类型还是数据的类型 变量存储的数据类型因为变量无类型但是存储的数据有
stringintfloat
数据类型转换
数据类型之间在特定的场景下是可以相互转换的如字符串转数字数字转字符串等。 为什么要转换类型
从文件中读取数字默认是字符串我们需要转成数字类型。input()语句默认结果是字符串如需要数字也需要转换。将数字转成字符串用写出到外部系统
常见的转成语句
语句函数说明int(x)将x转成一个整型float(x)将x转成一个浮点型str(x)将对象x转成字符串
注意这三个语句都是带有结果的返回值我们可以用print直接输出或者用变量存储结果值。
# 将数字变成字符串
num_str str(11)
print(type(num_str), num_str) # 结果class str 11# 浮点数转字符串
float_str str(11.11)
print(type(flost_str), flost_str) # 结果class str 11.11# 将字符串转成数字
num int(11)
print(type(num), num) # 结果class int 11
注意int([字符或者中文]) int(11.11) 将会报错 [ValueError: invalid literal for int() with xxxx]# 将字符串转成float
num_float float(11.11)
print(type(num_float), num_float) # 结果class float 11.11
注意float(11) 将输入 11.0# 整数转浮点数
float_num float(11)
输出11.0# 浮点数转整型会丢失精度
int_num int(11.11)
输入 11标识符
变量名字方法的名字类的名字等等
这些名字统一称之为标识符用来做内容的标识 python标识符命名规则
内容限定 标识符名称中 只允许出现这4类元素其余内容都不被允许 英文中文 不推荐数字 数字不可以开头下划线( _ ) 大小写敏感不可使用关键字 如果使用的大小写与关键字不一定则是可以使用如果跟关键字一模一样则不被允许
变量命名规范
见名知意 尽量做到看到名字就知道是什么意思确保在明了的前提下减少名字的长度 下划线命名法 多个单词组合变量名要使用下划线做分隔 英文字母全小写 命名变量中英文字母尽量全小写
运算符
算术运算符
运算符描述实例加两个对象相加-减得到负数或是一个数减去另一个数*乘两个数相乘或是返回被重复诺干次的字符串a*b输出结果/除两个数相除//取整除返回商的整数部分%取余返回除法的余数**指数a**b为10的20次方
赋值运算符
运算符描述实例赋值运算符把号右边的结果赋值给左边的变量
复合赋值运算符
运算符描述实例加法赋值运算符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
字符串扩展
字符串三种定义方式 单引号定义法 name ‘xxxxx’双引号定义法 name “xxxxxx”三引号定义法 name “”“xxxxx”“” 三引号定义法和多行注释的写法一样同样支持换行操作使用变量接受它他就是字符串不使用变量接收它就可以作为多行注释使用 字符串的引号嵌套 单引号定义法可以内含双引号双引号定义法可以内含单引号可以使用转义字符\来将引号解除作用变成普通字符串 字符串拼接 通过 号拼接 **注意**只能适用于字符串的拼接不能使用字符串与非字符串的拼接 字符串格式化
num 10
class_num 10
message 年段第%s班级共有%s人 % (num, class_num)其中 %s表示将变量变成字符串放入占位的地方这里将数字变成字符串放入
% 表示 我要占位
注意 多个变量占位变量要用括号括起来并按照占位的顺序引入
python 支持多种数据类型占位
1. %s 转成字符串
2. %d 转成整数
3. %f 转成浮点数格式化的精度控制 我们可以使用辅助符号“m.n”来控制数据的宽度和精度m控制宽度要求数数字很少使用设置宽度小于数字自身不生效.n 控制小数点精度要求是数字会进行小数的四舍五入 实例%5d: 表示将整数的宽度控制在5位如数字11被设置为5d就会变成 [空格][空格][空格]11 用三个空格补足宽度%5.2f, 表示将宽度控制在5将小数点精度设置为2。小数点和小数部分也算入宽度计算如对11.345设置了%7.2f后结果是 [空格][空格]11.35 2个空格补足宽度小数点部分限制2位精度四舍五入为.35%.2f 表示不限制宽度只设置小数点精度为2如11.345设置后为11.35字符串格式化方式2(快速格式化) 通过语法 f内容{变量} 的格式来快速格式化 fxxxx{name}xxxxx 不限数据类型不做精度控制 对表达式进行格式化 – 一条具有明确执行结果的代码语句 1 1 5 * 2 用法: 将上面的变量转变成表达式
name xxxx
stock_price 11.11
stock_code 100000
stock_price_daily_factor 1.2
growth_days 7print(f公司{name}, 股票代码:{stock_code} 当前股价{stock_price})
print(每日增长系数%.2f, 经过%d天 股价变成了%.2f % (stock_price_daily_factor, growth_days, stock_price * stock_price_daily_factor ** growth_days))
数据输入
input 语句函数 用来获取键盘输入数据输出print数据输入 input
使用方法使用input()语句可以从键盘上获取输入使用一个变量接受存储input语句获取的键盘输入数据即可代码
print(输入名字)
name input() # 回车结束输入
print(name)name input(输入名字)
print(name)
判断语句
布尔类型和比较运算符
布尔类型
字面量 True 表示真Flase 表示假 定义变量存储布尔类型数据 变量名称 布尔类型字面量
布尔类型不仅可以自定定义也可以通过计算的来也就是使用比较运算符进行运算得到的布尔类型的结果
比较运算符
运算符描述示例判断内容是否相等满足True不满足Falsea 3 b 3 a b为True!判断内容是否不相等a 1 b 3 a ! b True
if语句的基本格式
基本语法格式
if 要判断的条件:条件成立要做的事情例子代码
if age 18:print(已经成年)判断语句的结果必须是布尔类型True或者False
True会执行if内的代码语句
False则不会执行age int(input(你的年纪))
if age 18:print(你已经成年门票30)if age 18:print(你未成年门票10)
if else 语句
if 条件:满足 TODO
else:不满足 TODO例子
age int(input(你的年纪))
if age 18:print(你已经成年门票30)
else:print(你未成年门票10)if else 语句中 if和其他代码块条件满足时执行else搭配if的判断条件当不满足时候执行 if else 注意事项 else 不需要判断条件当if的条件不满足else执行else代码块同样需要4个空格作为缩进
if elif else 语句
if 条件1:满足条件1 TODO
elif 条件2:满足条件2 TODO
elif 条件3:满足条件3 TODO
else:都不满足 TODO例子
age int(input(你的年纪))
if age 60:print(大于60岁免费)
elif age 18:print(你已经成年门票30)
else:print(你未成年门票10)
注意判断是互斥且有顺序的
满足1 将不会执行2和3满足2 将不会执行3全不满足则进入elseelse可省略不写 效果等于几个独立的if判断空格缩进同样不可省略
判断语句的嵌套
if 条件1:满足条件1 TODOif 条件2:满足条件2 TODO
第二个if 属于第一个if内只有第一个if满足条件才会执行第二个if
嵌套的关键点在于空格缩进
通过空格缩进来决定语句之间的层次关系嵌套判断语句可以使用于多条件多层次的逻辑判断嵌套判断语句可以根据需求自由组合if elif else 来构建多层次判断嵌套判断语句一定要注意空格缩进Python通过空格缩进来决定层次关系
实战案例
import randomnum random.randint(1, 10) # 随机数 1到10以内的整型随机数
guess_num int(input(输入你要猜测的数字))if guess_num num:print(恭喜你猜中了)else:if guess_num num:print(大了)else:print(小了)guess_num int(input(输入你要猜测的数字))if guess_num num:print(恭喜你猜中了)else:if guess_num num:print(大了)else:print(小了)guess_num int(input(输入你要猜测的数字))if guess_num num:print(恭喜你猜中了)else:if guess_num num:print(f大了, 游戏结束数字为{num})else:print(f小了游戏结束数字为{num})循环语句
while循环的基础语法
while 条件:条件满足 TODO....直到条件不满足则退出循环
### 注意 只要条件一直满足会无限循环执行造成死循环例子
i 0
while i 100:print(i)i 1
# 循环输出0-99直到i 100 不满足i 100 退出循环例子求1-100的和
i 1
num_sum 0
while i 100:num_sum ii 1
print(num_sum)注意
条件需要提供布尔类型结果True继续 False停止空格缩进不能忘规划好循环终止条件否则将无限循环
while循环的基础案例
猜数字使用while改进
import random
num random.randint(1, 10) # 随机数 1到10以内的整型随机数
count 1
flag True
while flag:guess_num int(input(输入你要猜测的数字))if guess_num num:print(f恭喜你猜中了用猜了{count}次)flag Falseelse:if guess_num num:print(大了,继续)else:print(小了 继续)count 1
while循环的嵌套应用
while 条件1:条件满足 TODO....while 条件2:满足条件2 TODO....直到条件2不满足则退出循环直到条件1不满足则退出循环注意
注意条件的控制避免无限循环多层嵌套主要空格缩进来确定层次关系循环条件的控制层次越多越复杂需要细心
while循环的嵌套案例
补充知识
1. print输出不换行 在print语句中加入 end 即输出不换行
2. 制表符 \t 效果等于在键盘上按下tab键 可以让多行字符串进行对齐
案例 九九乘法表
i 1
while i 9:j 1while j i:print(f{j} * {i} {i * j}\t, end)j 1i 1print()for 循环的基础语法
除while循环外。python支持for循环语句 区别
while循环的循环条件是自定义自行控制循环条件for循环是一种“轮询”机制是对一批内容进行“逐个处理”
语法 for 临时变量 in 待处理数据集: 循环满足条件时执行的代码
从待处理数据集中逐个取出数据赋值给临时变量
语法中待处理数据集称之为序列类型 序列类型值其内容可以一个个依次取出来的一种类型包括
字符串列表元组等等
range语句获得一个简单的数字序列
语法1 range(num)获取一个从0开始到num结束的数字序列 不包含num本身如range(5) 得到数据为[0,1,2,3,4] 语法2 range(num1. num2)获取一个从num1开始到num2结束的数字序列不包含num2本身range(5, 10)获取的数据是[5, 6, 7, 8, 9] 语法3 range(num1, num2, step)获取一个从num1开始到num2结束的数字序列不包含num2本身数字之间的步长以step为准step默认为1range(5, 10, 2) 获取的数据为[5, 7, 9]
变量作用域
for循环中的临时变量其作用域限定为 循环内这种限定 是编程规范的限定而非强制性限定不遵守也能正常运行但是不建议这么做如需访问临时变量可以预先在循环外定义它
语法
例子遍历字符串
name ccyylllc
for x in name:print(x)# for 循环将字符串的内容依次取出for循环也被称为遍历循环例子 计算a出现的次数
count 0
str xasasasagagsdga
for s in str:if s a:count 1
print(count)例子 1 - 100 不包含100 有几个偶数
count 0
for i in range(1, 100):if i % 2 0:count 1
print(count)
注意
无法定义循环条件只能被动取出数据处理循环内的语句需要有空格缩进
for循环的嵌套应用
语法 for 临时变量1 in 待处理数据集: 满足循环条件的TODO … for 临时变量2 in 待处理数据集: 满足循环条件的TODO
注意事项
注意缩进for循环可以和while循环相互嵌套使用
for i in range(1, 10):j ifor j in range(1, i1):print(f{j} * {i} {i * j}\t, end)print()
循环中断 break和continue
continue
continue关键字用于中断本次循环直接进入下一次的循环for和while循环效果一直
break
break关键字同样只可以控制 它所在的循环结束for和while循环效果一直
在嵌套循环中只能作用在所在循环上无法对上层循环起作用
综合案例
import randomall_price 10000
person_num 20
i 1
while i 20:score random.randint(1, 10)if score 5:print(f第{i}号员工绩效{score}低于5分不发工资)else:if all_price 0:print(工资发完了下个月再说)breakall_price - 1000print(f第{i}号员工绩效{score}发工资1000公司余额{all_price})i 1Python 函数
定义
是组织好的可重复使用用来实现特定功能的代码段 为什么要使用函数
为了得到一个针对特定需求可供重复使用的代码段提高程序的复用性减少重复代码提高开发效率
函数的定义
语法 def 函数名(传入参数): 函数体 return 返回值 调用 函数名(参数) 注意事项
参数如不需要可以省略返回值不需要可以省略函数必须先定义后使用
函数的参数
传入的参数的功能是在函数进行计算的时候接收外部调用时提供的数据函数定义中提供的参数称之为形式参数表示函数声明将要使用几个参数 参数之间用逗号隔开 函数调用中提供的数据称之为实例参数标识函数执行时真正使用的参数值 传入的时候按照顺序传入数据使用逗号分隔
def check(x):if x 37.5:print(你已经发烧需要隔离)else:print(体温正常)
check(37.7)函数的返回值
定义函数在执行完成后返回给调用者的结果 返回值的应用语法
使用关键字 return来返回结果
注意
函数体在遇到return后就结束了所以return后面的代码不会执行
None类型 如果没有使用return语句返回数据那么函数有返回值吗 有的Python中有一个特色的字面量None其类型是class ‘NoneType’ 无返回值的函数实际上就是返回了None这个字面量 None表示 空的无实际意义 函数返回的None 就标识这个函数没有返回什么有意义的内容也就是返回了空的意思 应用场景
用在函数无返回值上用在if判断上 在if判断中None等同于False一般用于在函数中主动返回None配合if判断做相关处理 用于声明无内容的变量上 定义变量但是暂时不需要有具体在可以使用None来代替
函数说明文档
def check(x):返回判断结果:param x::return:if x 37.5:print(你已经发烧需要隔离)else:print(体温正常)# 快捷注释在函数名称下面输入6个引号后在中间回车函数的嵌套调用
指一个函数里面又调用了另外一个函数 执行流程
函数A中执行到调用的函数B的语句会将函数B全部执行完成后继续执行函数A的剩余内容
变量的作用域
什么是局部变量 作用范围在函数内部在函数外部无法使用 什么是全局变量 在函数内部和外部均可使用 如果将函数内定义的变量声明为全局变量 使用global关键字global变量
num 200
def change_num1():num 100def change_num2():global numnum 300change_num1()
print(num) # 结果 200 因为change_num1 赋值的num的局部变量
change_num2()
print(num) #结果 300 使用global声明变量为全局变量综合案例
money 20000
name xxxxdef init():print(-----------主菜单-----------)print(查询余额 1)print(存款 2)print(取款 3)print(退出 4)return int(input(请输入你的选择))def search():print(----------查询余额-----------)print(f{name}的剩余金额{money})def getOrSet(use_money, flag):global moneyif flag 1:money use_moneyelse:money - use_moneyprint(f你的{存款 if flag 1 else 取款}操作成功现在余额{money})def close():print(退出成功)if __name__ __main__:while True:ops init()if ops 1:search()elif ops 2:getOrSet(200, 1)elif ops 3:getOrSet(400, 2)elif ops 4:close()breakelse:print(输入错误请重新输入)continue
数据容器
定义 一种可以容纳多份数据的数据类型容纳的每一份数据称之为1个元素每一个元素可以是任意类型的数据如字符串数字布尔等 特点
是否支持重复元素是否可以修改是否有序等等
分为5类
列表list元组tuple字符串str集合set字典dict
list 列表
列表的定义
# 字面量
[元素1 元素2 元素3 元素4 ...]
# 定义元素
变量名称 [元素1 元素2 元素3 元素4 ...]
# 定义空列表
变量名称 []
变量名称 list()注意列表可以一次存储多个数据且可以为不同的数据类型支持嵌套列表的下标索引
下标的索引是什么列表的每一个元素都有编号成称之为下标索引 从前往后的方向编号从0开始递增从后往前的方向编号从-1开始递减 如何通过下标索引取出对应的元素 列表[下标],即可取出 下标索引的注意事项 要注意下标索引的取值范围超出范围无法取出元素并且会报错
列表的常用操作
列表的查询功能方法
**查找某元素的下标 ** 功能查找指定元素在列表的下标如果没找到则报错ValueError语法 列表.index(元素) index就是列表元素对象变量内置的方法函数 统计列表内有多少元素 语法 len(列表)
列表的修改功能方法
修改特定位置索引的元素值语法 列表[下标] 值 可以使用如上写法直接对指定下标正向反向都可以的值进行重新复制修改 插入元素 语法 列表.insert(下标元素) 在指定的下标位置插入指定的元素 追加元素 语法列表.append(元素) 将指定元素追加到列表的尾部 追加元素2 语法列表.extend(其他数据容器) 将其他数据容器的内容取出依次追加到列表尾部 删除元素 语法1 del 列表[下标]语法2 列表.pop(下标) 删除某元素在列表中的第一匹配项 语法 列表.remove(元素) 清空列表内容 语法 列表.clear() 统计某元素在列表中的数量 语法列表.count(元素)
特点
可以容纳多个元素上限 2**63-1可以容纳不同类型的元素混装数据是有序存储的有下标序号允许重复数据存在可以修改增加删除元素等等
my_list [demo1, demo2, demo3, demo4]
print(my_list.index(demo1)) # 0
print(my_list.index(demo0)) # ValueError: demo0 is not in listmy_list[0] demo0
my_list[-1] demo-1
my_list[4] demo4 # IndexError: list assignment index out of range
print(my_list[0]) # demo0
print(my_list[-1]) # demo-1
print(my_list[4])list_len len(my_list)
print(list_len) # 4my_list.insert(3, demo5)
print(my_list) # [demo1, demo2, demo3, demo5, demo4]my_list.append(demo6)
print(my_list) # [demo1, demo2, demo3, demo5, demo4, demo6]my_list.extend([demo7, demo8, demo10])
print(my_list) # [demo1, demo2, demo3, demo5, demo4, demo6, demo7, demo8, demo10]del my_list[8]
print(my_list) # [demo1, demo2, demo3, demo5, demo4, demo6, demo7, demo8]
del_str my_list.pop(7)
print(my_list, del_str) # [demo1, demo2, demo3, demo5, demo4, demo6, demo7] demo8my_list.remove(demo2)
print(my_list) # [demo1, demo3, demo5, demo4, demo6, demo7]num my_list.count(demo1)
print(num) # 1my_list.clear()
print(my_list) # []
有一个列表内容是[21, 25, 21, 23, 22, 20], 记录一批学生年纪
# 定义一个列表并用变量接受它
my_list [21, 25, 21, 23, 22, 20]
# 追加一个数字31到列表微博
my_list.append(31)
print(my_list) # [21, 25, 21, 23, 22, 20, 31]
# 追加一个新列表[29, 33, 30] 到尾部
my_list.extend([29, 33, 30])
print(my_list) # [21, 25, 21, 23, 22, 20, 31, 29, 33, 30]
# 取出第一个元素 [21]
num1 my_list.pop(0)
print(num1) # 21
# 取出最后一个元素
num2 my_list.pop(len(my_list) - 1)
print(num2) # 30
# 查找元素31在列表中下标位置
print(my_list.index(31)) # 5list的遍历
使用while index 0 while index len(list): print(list[index]) index 1 使用for循环 for 临时变量 in 数据容器 对临时变量进行处理 for element in list: print(element) while循环和for循环都是循环语句但是细节不同
在循环上控制 while循环可以自定循环条件。并自行控制for循环不可以自定循环条件只可以一个个从容器取出数据 在无限循环上 while循环可以通过条件控制做到无限循环for循环理论上不可以因为被遍历的容器容量不是无限的 在使用场景上 while循环适用于任何想要循环的场景for循环适用于遍历数据容器的场景或者简单的固定次数循环场景
数据容器tuple(元组)
为什么需要元组如果想要传递的信息不被篡改列表就不合适 元组用列表一样都是可以封装多个不同类型的元素在内。 但是最大的不同点在于 元组一旦定义完成就不可修改 所以当我们需要在程序内封装数据又不希望封装的数据被篡改那么元组就非常合适 定义元组
定义元组使用小括号且使用逗号合开各个数据数据可以是不同的数据类型
# 定义元组字面量
(元素, 元素, .... , 元素)
# 定义元组变量
变量名称 (元素, 元素, .... , 元素)
# 定义空元组
变量名称 ()
变量名称 tuple() 注意元组只有一个数据这个数据后面要添加逗号t1 ((1, 2, 3), (4, 5, 6))# 通过下标索引取出数据 6
num t1[1][2]元组的相关操作
index(元素) 查找某个数据如果数据存在返回对应的下标否则报错count(元素) 统计某个数据在当前元组出现的次数len(元组) 统计元组内的元素个数
# 元组遍历
# while遍历
index 0
while index len(元组):print(元组[index])index 1
# for遍历
for item in 元组:print(item)元组特点:
可以容纳多个数据可以容纳不同类型的数据数据是有序存储 – 下标索引允许重复数据存在不可以修改整加或者删除支持for循环
元组注意事项
不可以修改元组的内容否则会直接报错可以修改元组内的list修改元素增加删除反转等等
数据容器str(字符串)
字符串是字符的容器一个字符串可以存放任意数量的字符 字符串的下标索引 和其他容器一样列表元组一样字符串也可以通过下标来进行访问
从前向后下标为0开始从后向前下标为-1开始
同元组一样字符串是一个无法修改的数据容器 如果必须要修改只能得到新的字符串老字符串无法修改
字符串常用的操作
字符串的替换 语法字符串.replace(字符串1 字符串2)功能将字符串内的全部内容字符串1 替换成字符串2注意不是修改字符串本身。而是得到一个新的字符串 字符串分割 语法 字符串.split(分割符字符串)功能按照指定的分隔符字符串将字符串划分为多个字符串并存入列表对象中注意字符串本身不变而是得到一个列表对象 字符串的规整操作去前后空格 语法字符串.strip() 字符串的规整操作 去前后指定字符串 语法字符串.strip(字符串) 统计字符串某个字符串出现的次数 语法 count(字符串) 统计字符串长度 语法len(字符串)
my_str iitemasdadfad badfa
my_str2 12iitemasdadfad badfa21
# index 方法
print(my_str.index(ad)) # 8# replace方法
print(my_str.replace(ad, ,,)) # iitemasd,,f,, b,,fa# split方法
print(my_str.split(a)) # [iitem, sd, df, d b, df, ]
print(my_str.split(a, 2)) # [iitem, sd, dfad badfa ]# strip方法
print(my_str.strip()) # iitemasdadfad badfa
print(my_str2.strip(12)) # iitemasdadfad badfa
# 注意传入的是12其实是1和2 都会被移除是按照单个字符# 统计字符串中某字符串出现的次数
print(my_str.count(ab)) # 0
# 统计字符串的长度
print(len(my_str)) # 21数据容器的切片
序列是指内容连续有序可使用下标索引的一类数据容器 列表元组字符串均可以视为序列 序列支持切片即列表元组字符串支持进行切片操作 切片从一个序列中取出一个子序列 语法序列[起始下标: 结束下标: 步长] 表示从序列中从指定位置开始依次取出元素到指定位置结束得到一个新序列
起始下标表示从何处开始可以留空留空则表示从头开始结束下标不含表示何处结束可以留空留空视为截取到结果步长表示依次取出元素的间隔 步长1表示一个个取元素步长2表示每次跳过一个取元素步长N表示每次跳过N-1个元素取步长为负数表示反向取注意起始下标和结束下标也要反向标记 注意此操作不会影响序列本身而是会得到一个新的序列
# 对list进行切片从1开始4结束步长1
my_list [0, 1, 2, 3, 4, 5, 6]
print(my_list[1:4]) # 步长1可以默认不写 [1, 2, 3]# 对tuple进行切片从头开始到最后结束步长1
my_tuple (0, 1, 2, 3, 4, 5, 6)
print(my_tuple[:]) # 起始和结束不写表示从头到尾步长为1省略 (0, 1, 2, 3, 4, 5, 6)# 对str进行切片从头开始到最后结束步长2
my_str 01234567
print(my_str[::2]) # 0246# 对str进行切片从头开始到最后结束步长-1
my_str2 01234567
print(my_str2[::-1]) # 等同于将序列反转 76543210# 对列表进行切片从3开始到1 结束步长-1
my_list2 [0, 1, 2, 3, 4, 5, 6]
print(my_list2[3:1:-1]) # [3, 2]# 对元组进行切片从头开始到尾结束步长-2
my_tuple2 (0, 1, 2, 3, 4, 5, 6)
print(my_tuple2[::-2]) # (6, 4, 2, 0)数据容器set集合
语法
# 定义集合字面量
{元素, 元素, 元素, ..., 元素}
# 定义集合变量
变量名称 {元素, 元素, 元素, ..., 元素}
# 定义空集合
变量名称 set()集合的操作因为集合是无序的所以集合不支持下标索引但是和列表一样是允许修改的
添加新元素 语法集合.add(元素)将指定元素添加到集合内结果集合本身被修好移除了新元素 移除元素 语法集合.remove(元素)将指定元素从集合内移除结果集合本身被修好移除了新元素 从集合中随机取出元素 语法集合.pop()功能从集合中随机取出一个元素结果会得到一个元素的结果同时集合本身被修改元素被移除 清空集合 语法集合.clear() 功能清空集合结果集合本身被清空 取出两个集合的差集 语法集合1.difference(集合2)功能取出集合1和集合2的差集集合1有而集合2没有的结果得到一个新集合集合1和集合2不变 消除两个集合的差集 语法集合1.difference_update(集合2)功能对比集合1和集合2在集合1内删除和集合2相同的元素结果集合1被修改集合2不变 两个集合合并 语法集合1.union(集合2)功能将集合1和集合2组成新集合结果得到新集合集合1和集合2不变
my_set {demo1, demo2, demo3, demo4}# 添加新元素
my_set.add(demo5)
print(my_set) # {demo3, demo4, demo1, demo5, demo2} 输出没按照顺序因为他是无序的# 移除新元素
my_set.remove(demo5)
print(my_set) # {demo3, demo4, demo1, demo2}# 随机去除一个元素
str my_set.pop()
print(str) # demo3# 清空集合
my_set.clear()
print(my_set) # set()# 取出两个集合的差集
set1 {1, 2, 3, 4}
set2 {3, 4, 7, 8}
set3 set1.difference(set2)
print(set1) # {1, 2, 3, 4}
print(set2) # {8, 3, 4, 7}
print(set3) # {1, 2}# 消除两个集合的差集
set1 {1, 2, 3, 4}
set2 {3, 4, 7, 8}
set3 set1.difference_update(set2)
print(set1) # {1, 2}
print(set2) # {{8, 3, 4, 7}
print(set3) # None# 2个集合合并为1个
set1 {1, 2, 3, 4}
set2 {3, 4, 7, 8}
set3 set1.union(set2)
print(set1) # {1, 2, 3, 4}
print(set2) # {8, 3, 4, 7}
print(set3) # {1, 2, 3, 4, 7, 8}# 统计集合元素的数量
set1 {1, 2, 3, 4}
print(len(set1)) # 4# 集合遍历
set1 {1, 2, 3, 4}
for item in set1:print(item)特点
可以容纳多个数据可以容纳不同类型的数据数据是无序存储的不支持下标索引不允许重复数据存在可以修改(增删改查)支持for循环
数据容器dict字典映射
定义同样使用{}不过存储的元素是一个个的
# 定义字典字面量
{key: value, key: value, key: value, ..., key: value}
# 定义字典变量
my_dict {key: value, key: value, key: value, ..., key: value}
# 定义空字典
my_dict {}
my_dict dict()数据的获取
字典可以通过key值去取得对应的value
注意事项
键值对的key和value可以是任意类型key不能为字典字典内的key不允许重复重复添加等同于覆盖原有数据字典不支持下标索引而是用过key检索value
字典常用超出
新增元素 语法字典[key] value结果字典被修改新增了元素 更新元素 语法字典[key] value结果字典被修改元素被更新注意字典key不可以重复所以对已存在的key执行上述操作就是更新value值 删除元素 语法字典.pop(key)结果获取指定key的value 清空字典 语法字典.clear()结果字典被修改元素被清空 获取全部的key 语法字典.keys()结果得到字典中全部的key
my_dict {demo1: 1, demo2: 2, demo3: 3}# 新增元素
my_dict[demo4] 4
print(my_dict) # {demo1: 1, demo2: 2, demo3: 3, demo4: 4}# 更新元素
my_dict[demo3] 33
print(my_dict) # {demo1: 1, demo2: 2, demo3: 33, demo4: 4}# 删除元素
my_dict.pop(demo3)
print(my_dict) # {demo1: 1, demo2: 2, demo4: 4}# 清空元素
my_dict.clear()
print(my_dict) # {}# 获取全部的key
my_dict {demo1: 1, demo2: 2, demo3: 3}
print(my_dict.keys()) # dict_keys([demo1, demo2, demo3])
# 遍历字典
for item in my_dict.keys():print(item, end) # dict_keys([demo1, demo2, demo3])print(my_dict[item], end) # demo11demo22demo33# 统计字典内的元素数量
my_dict {demo1: 1, demo2: 2, demo3: 3}
print(len(my_dict)) # 3
数据容器总结对比
是否支付下标索引 支持列表元组字符串 – 序列类型不支持集合字典 – 非序列类型 是否支持重复元素 支持列表元组字符串 – 序列类型不支持集合字典 – 非序列类型 是否可以修改 支持 列表集合字典不支持元组字符串
数据容器的通用操作
my_list [1, 2, 3, 4, 5]
my_tuple (1, 2, 3, 4, 5)
my_Str adbadfgh
my_dict {key1: 1, key2: 2, key3: 3}
my_set {1, 2, 3, 4, 5}# len 元素个数
print(len(my_list)) # 5
print(len(my_tuple)) # 5
print(len(my_Str)) # 8
print(len(my_dict)) # 3
print(len(my_set)) # 5# max最大元素
print(max(my_list)) # 5
print(max(my_tuple)) # 5
print(max(my_Str)) # h
print(max(my_dict)) # key3
print(max(my_set)) # 5# min最小元素
print(min(my_list)) # 1
print(min(my_tuple)) # 1
print(min(my_Str)) # a
print(min(my_dict)) # key1
print(min(my_set)) # 1# 类型转换 容器转列表
print(list(my_list)) # [1, 2, 3, 4, 5]
print(list(my_Str)) # [a, d, b, a, d, f, g, h]
print(list(my_tuple)) # [1, 2, 3, 4, 5]
print(list(my_set)) # [1, 2, 3, 4, 5]
print(list(my_dict)) # [key1, key2, key3]# 容器转元组
print(tuple(my_list)) # (1, 2, 3, 4, 5)
print(tuple(my_Str)) # (a, d, b, a, d, f, g, h)
print(tuple(my_tuple)) # (1, 2, 3, 4, 5)
print(tuple(my_set)) # (1, 2, 3, 4, 5)
print(tuple(my_dict)) # (key1, key2, key3)# 容器转集合
print(set(my_list)) # {1, 2, 3, 4, 5}
print(set(my_Str)) # {g, d, f, h, b, a}
print(set(my_tuple)) # {1, 2, 3, 4, 5}
print(set(my_set)) # {1, 2, 3, 4, 5}
print(set(my_dict)) # {key1, key2, key3}# 容器转字符串
print(str(my_list)) # [1, 2, 3, 4, 5]
print(str(my_Str)) # adbadfgh
print(str(my_tuple)) # (1, 2, 3, 4, 5)
print(str(my_set)) # {1, 2, 3, 4, 5}
print(str(my_dict)) # {key1: 1, key2: 2, key3: 3}
综合案例
函数的多返回值
示例 def test_return(): return 1, 2 x, y test_return 按照返回值的顺序写对应顺序的多个变量接收即可变量之间用逗号隔开支持不同类型的数据return
函数的多种传参方法
使用方式上的不同函数有4中常见参数使用方式
位置参数
def user_info(name, age, gender):TODO
user_info(name, age, gender)
# 注意 传递的参数和定义的参数的顺序及个数必须一致关键字参数
# 关键字参数函数调用时通过“键值”形式传递参数
# 作用可以让函数更加清晰容易使用同时也消除了参数的顺序
def user_info(name, age, gender)TODO
# 关键字传参
user_info(name name, age age, gender gender)
# 可以不按照固定顺序
user_info(age age, gender gender, name name)
# 可以和位置参数混用位置参数必须在前面且匹配参数顺序
user_info(name, age age, gender gender)
# 注意函数调用时如果有位置参数时位置参数必须在关键字参数前面但关键字参数之间不存在先后顺序缺省参数 缺省参数也叫默认参数用于定义函数为参数提供默认值调用函数是可不传该默认参数的值注意 所有位置参数必须出现在默认参数前包括函数的定义和调用
作用 当调用函数时没有传递参数就会使用默认是用缺省参数对应的值def user_info(name, age, gender 男)TODOuser_info(name, age)
user_info(name, age, gender)注意
函数调用时如果为缺省参数传递则修改默认值否则使用这个默认值不定长参数 不定长参数也叫可变参数用于不确定调用的时候会传递多少个参数不传参也可以的场景
作用 当调用函数时不确定参数的个数时可以使用不定长参数不定长参数的类型
1.位置传递
2.关键字传递# 位置传递
def user_info(*args):TODO
user_info(name)
user_info(name,age)注意传进的所有参数都会被args变量收集它会根据传进参数的位置合并成一个元组args是元组类型这就是位置传递# 关键字传递
def user_info(**kwargs):TODO
user_info(name name, age age)# 注意参数是“键值对”形式的情况下都会被keyWords接收同时会根据键值对组成字典函数作为参数传递
def test_func(compute):result compute(1, 2)TODO
def compute(x, y):TODOtest_func(compute)函数compute作为参数传入了test_func函数中使用
test_func需要一个函数作为参数传入这个函数需要接受两个数字进行计算计算逻辑由这个被传入函数决定
compute函数接受2个数字对其进行计算compute函数作为参数传递给了test_func函数使用
最终在test_func函数内部由传入的compute函数完成对数字的计算操作
这是一种计算逻辑的传递而非数据的传递
任何逻辑都可以自定定义并作为函数传入lambda匿名函数 函数定义中
def关键字可以定义带有名称的函数lambda关键字可以定义匿名函数无名称
有名称的函数可以基于名称重复使用 无名称的匿名函数只可临时使用一次
匿名函数定义语法 lambda 传入参数: 函数体一行代码
lambda是关键字 表示定义匿名函数传入参数表示匿名函数的形式参数如x, y表示接受2个形式参数函数体就是函数的执行逻辑要注意只能写一行无法写多行代码
def test_func(compute):result compute(1, 2)print(result)test_func(lambda x, y: x y)文件操作
文件编码
什么是编码 编码就是一种规则集合记录了内容和二进制进行相互转换的逻辑编码有许多种我们最常见的是UTF-8编码 为什么要使用编码 计算机只认识0和1所以需要将内容翻译成0和1才能保存在计算机中同样也需要编码将计算机保存的0和1反向翻译回可以识别的内容
文件读取
open()打开函数
在python使用open函数可以打开一个已经存在的文件或者创建一个新的文件
open(name, mode, encoding)
name: 要打开的目标文件名的字符串可以包含文件所在的具体路径
mode: 设置打开文件的模式访问模式只读写入 追加等等
encoding编码格式实例代码
f open(text.txt,r,encodingutf-8)
注意encoding的顺序不是第三位所以不能用位置参数用关键字参数直接指定、注意事项此时的‘f’是‘open’函数的文件对象
############################################################
mode 常用的三种基础访问模式
r: 以只读方式打开文件文件的指针将会放在文件的开头这是默认方式
w: 打开一个文件只用于写入如果该文件已存在则打开文件并从开头开始编辑原有内容会被删除如果该文件不存在创建新文件
a: 打开一个文件用于追加如果该文件写存在新的内容将会写入到已有的内容之后如果该文件不存在创建新文件进行写入读取相关操作
read() 方法 语法 文件对象.read(num)num表示要从文件中读取的数据的长度单位字节如果没有传入num那么表示读取文件中所有的数据 readlines()方法 readlines()可以按照行的方式把整个文件中的内容进行一次性读取并且返回的是一个列表其中每一行的数据为一个元素 readline()方法 一次读取一行内容 语法文件对象.readline() for循环读取文件行 for line in open(“文件位置”, “r”) print(line) 每一个line临时变量就记录了文件的一行数据 close() 关闭文件对象 最后通过close关闭文件对象也就是关闭对文件的占用最用不调用close同时程序没有停止运行那么这个文件将一直被python程序占用 with open(“文件”, “r”) as f: f.readlines() 通过with open()的语句块中对文件进行操作可以在操作完成后自动关闭close文件避免遗忘掉close方法 在python使用open函数可以打开一个已经存在的文件或者创建一个新的文件
open(name, mode, encoding)
name: 要打开的目标文件名的字符串可以包含文件所在的具体路径
mode: 设置打开文件的模式访问模式只读写入 追加等等
encoding编码格式实例代码
f open(text.txt,r,encodingutf-8)
注意encoding的顺序不是第三位所以不能用位置参数用关键字参数直接指定、注意事项此时的‘f’是‘open’函数的文件对象
# 打开文件
f open(D:/Desktop/test.txt, r, encodingutf-8)
print(type(f)) # class _io.TextIOWrapper
# 读取文件 --- read()
print(f 读取10个字节的结果, f.read(10)) # f 读取10个字节的结果 1111111111
print(f 读取全部的结果, f.read()) # 文件全部数据
f.close()
# 读取文件 readlines()
f open(D:/Desktop/test.txt, r, encodingutf-8)
lines f.readlines()
print(type(lines)) # class list
print(lines) # [11111111111111111111111\n, 22222222222222222222222\n, 333333333333333333333333\n,
# 44444444444444444444444444\n, 55555555555555555555555555\n, 6666666666666666666666666666\n,
# 77777777777777777777777777777\n, 8888888888888888888888888888888\n, 9999999999999999999999999999999999\n,
# 101010101010101010101010101010101010\n, 11111111111111111111111111111111111111111]
f.close()
# 读取文件 readline() 一次读取一行
f open(D:/Desktop/test.txt, r, encodingutf-8)
line f.readline()
print(type(line)) # class str
print(line) # 11111111111111111111111
f.close()count 0
with open(D:/Desktop/test.txt, r, encodingutf-8) as f:for item in f.readlines():count item.count(111)print(count) # 20
文件写入
写入快速入门 案例演示
# 打开文件
f open(py.txt, w)
# 文件写入
f.write(hello, word)
# 内容刷新
f.flush()## 注意
1. 直接调用write内容并为真正写入文件而是会积攒在程序的内存里称之为缓冲区
2. 当调用flush的时候内容会真正写入文件
3. 这样做的避免频繁的操作硬盘导致效率下降赞一堆一次性写磁盘写入文件使用open函数“w”模式进行写入 写入的方法有
write() 写入内容flush(), 刷新内容到硬盘中
注意实现
w模式文件不存在会创建新文件w模式文件不存在会清空原有内容close()方法带有flush()方法的功能
文件追加
案例演示
# 1 打开文件通过a模式打开即可
f open(文件, a)# 2. 文件写入
f.write(hello world)#3. 内容刷新
f.flush()## 注意
1. a模式下文件不存在会创建文件
2. a模式下文件存在会在最后追加写入文件文件操作综合案例 with open(bill.txt, r, encodingutf-8) as fr:with open(bill.txt.bak, w, encodingutf-8) as fw:for line in fr:line line.strip()if line.strip(,)[4] 测试:continuefw.write(line)fw.write(\n)
python 异常、模块、包
什么是异常
当我们检测到一个错误时Python解释器就无法继续执行了反而出现了一些错误的提示这就是所谓的“异常”我们常说的bug
异常的捕获方法
基本语法
try:可能发生错误的代码
except:如果出现异常执行的代码快速入门
# 需求尝试以r模式打开文件如果文件不存在则以w方式打开
try:f open(linux.txt,r)
except:f open(linux.txt,w)捕获指定异常
基本语法
try:print(name)
except NameError as e:print(name未定义)## 注意事项
1. 如果尝试执行的代码得异常和要捕获的异常类型不一致则无法捕获异常
2. 一般try下方只放一行尝试执行的代码捕获多个异常
基本语法
## 当捕获多个异常时可以把要捕获的异常类型的名字放在except后并用元组的方式进行书写
try:print(1/0)
except (NameError, ZeroDivisionError) as e:print(异常);# 捕获所有的异常
try:print(1/0)
except Exception as e:print(异常);异常else
else表示如果没有异常要执行的代码----可写可不写
try:print(1/0)
except Exception as e:print(异常);
else:print(没有异常执行的代码);异常的finally
finally表示无聊是否异常都要执行的代码。例如关闭文件
try:print(1/0)
except Exception as e:print(异常);
else:print(没有异常执行的代码);
finally:print(用了一定会走)异常的传递
异常是具有传递性的 当函数func01中发生异常并且没有捕获处理这个异常的时候异常会传递到函数fun02当fun02也没有捕获处理这个异常的时候main函数会捕获这个异常这就是异常的传递性 提示
当所有函数都没有捕获异常的时候程序就会报错
# 异常捕获
def fun01():print(这是func01开始)num 1 / 0print(这是func01结束)def fun02():print(这是func02开始)fun01()print(这是func02结束)if __name__ __main__:try:fun02()except Exception as e:print(e)
############
这是func02开始
这是func01开始
division by zero# 异常没有捕获
def fun01():print(这是func01开始)num 1 / 0print(这是func01结束)def fun02():print(这是func02开始)fun01()print(这是func02结束)if __name__ __main__:fun02()
################
这是func02开始
这是func01开始
Traceback (most recent call last):File D:\Desktop\pySpace\py-demo\exceptiondemo.py, line 14, in modulefun02()File D:\Desktop\pySpace\py-demo\exceptiondemo.py, line 9, in fun02fun01()File D:\Desktop\pySpace\py-demo\exceptiondemo.py, line 3, in fun01num 1 / 0~~^~~
ZeroDivisionError: division by zeroPython模块
什么是模块
python模块module是一个python文件以.py结尾模块能定义函数类和变量。模块里也能包含可执行的代码。
模块的作用
python中有很多各种不同的模块每一个模块都可以帮助我们快速的实现一些功能例如实现和时间相关的功能可以使用time模块我们可以认为一个模块就是第一个工具包每一个工具包都有各种不同的工具供我们使用进而实现各种不同的功能
模块导入的方式
模块在使用前需要先导入导入的语法如下 [from 模块名] import [模块 | 类 | 变量 | 函数 | *] [as 别名] 常用的组合
import 模块名from 模块名 import 类、变量、方法等from 模块名 import *import 模块名 as 别名from 模块名 import 功能名 as 别名
# 使用import 导入time模块使用sleep功能
import timetime.sleep(2000)# 使用from 导入time的sleep
from time import sleep
sleep(2000)# 使用* 导入time模块的全部功能
from time import *
sleep(2000)# 使用as给特定功能加上别名
from time import sleep as s
s(3000)自定义模块的导入
##### my_module
def test(a, b):print(a b)
##### my_module2
def test(a, b):print(a - b)
#### my_module3
__add__ [test2, test3]def test(a, b):print(a - b)def test2(a, b):print(a * b)def test3(a, b):print(a / b)# 导入自定义模块使用
import my_modulemy_module.test(1, 2)# 导入不同模块的同名功能
from my_module import test
from my_module2 import test
## 注意 当导入多个模块的时候且模块内有同名功能当调用这个同名功能的时候调用到的是后面导入的模块的功能
test(2, 1)# __main__变量
只有当程序是直接执行的才会进入 if内部如果是被导入的则if无法进入# __all__变量
# 如果一个模块文件中有‘__all__’变量当使用‘from xxx import *’导入时只能导入这个列表中的元素python包
什么是python包
从物理上看包就是一个文件夹在该文件夹下包好了一个_init_.py 文件该文件夹可用于包含多个模块文件从逻辑上看包的本质还是模块包的作用当我们的模块文件越来越多时包可以帮助我们管理这些模块包的作用就是包含多个模块但是包的本质还是模块
导入包
方式一
import 包名.模块名 | 包名.模块名.目标方式二
from 包名 import * | 模块名.目标
## 注意必须在__init__.py文件里面添加__add__ [] 控制允许导入的模块列表
第三方包
在python中有许多第三方包非官方
科学计算中常用的numpy包数据分析常用的pandas包大数据计算中常用的pysparkapache-flink包图形可视化常用的matplotlibpyecharts人工智能常用的tensorflow
但是由于是第三方包python没有内置所以我们需要安装才可以导入使用
pip
第三方包安装非常简单只需要使用python内置的pip程序即可
pip install 如 pip install numpy
综合案例 my_utils包# __init__.py
__all__ [str_util, file_util]# file_util.py
def print_file_info(file_name):f open(file_name, r, encodingutf-8)try:context f.read()print(context)except Exception:print(文件不存在)finally:f.close()def add_file_data(file_name, data):with open(file_name, a, encodingutf-8) as f:f.write(data)f.close()# str_util.py
def str_reverser(s):return reversed(s)def sub_str(s, x, y):return s[x:y]# mian中使用
from my_utils import str_util, file_utilif __name__ __main__:print(str_util.str_reverser(asdfghj))print(str_util.sub_str(asdfghhh, 2, 6))file_util.add_file_data(pydemo.txt, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxxxxxxxxxx)file_util.print_file_info(pydemo.txt)
Python JSON数据格式的转换
什么是json
json是一种轻量级的数据交互格式可以按照json指定的格式去组织和数据封装json本质上是一个特定格式的字符串
主要功能json就是一种在各个编程语言中流通的数据格式负责不同编程语言中的数据传递和交互类似与
国际通用语言–英语中国民族不同地区的通用语言—普通话
python数据和JSON数据的相互转化
# 导入json模块
import json# 准备符合格式json格式要求的python数据
data [{name:老王, age: 18},{name:老名, age: 16}]# 通过json.dumps(data)方法把python数据转成json数据
data json.dumps(data)
print(data) # [{name: \u8001\u738b, age: 18}, {name: \u8001\u540d, age: 16}]
# 加入ensure_asciiFalse [{name: 老王, age: 18}, {name: 老名, age: 16}]# 通过json.loads(data)方法把json数据转化为python数据
data json.loads(data)
print(data) # [{name: 老王, age: 18}, {name: 老名, age: 16}]python面向对象
初识对象
在程序中是可以做到和生活中那样设计表格生产表格填写表格的组织形式的
在程序中设计表格称之为设计类 class在程序中打印生产表格称之为创建对象在程序中填写表格称之为对象属性复制
# 设计一个类
class Student:name Noneage Nonegender None
# 创建一个对象
stu_1 Student()
# 对象属性进行赋值
stu_1.name 张三
stu_1.age 18
stu_1.gender 女
# 获取对象中记录的信息
print(stu_1.name, stu_1.age, stu_1.gender) # 张三 18 女类的基本语法 class 类名称: 类的属性 类的行为 class是关键字表示要定义类了类的属性即定义在类中的变量类的行为即定义在类中的函数成员方法
创建类对象的语法 对象 类名称() 成员方法
什么是类的行为方法
class student:name Noneage Nonedef say_hi(self):print(f大家好我是{self.name})可以看出
类中 不仅可以定义属性用来记录数据类中 也可以定义函数用来记录行为
其中
类中定义的属性变量我们称之为成员变量类中定义的行为函数, 我们称之为成员方法
成员方法的定义语法
在类中定义成员方法和定义函数基本一致但仍有细微区别 def 方法名(self, 形参1, …, 形参N): 方法体 可以看出在方法定义的参数列表中有一个self关键字 self关键字是成员方法定义的时候必须填写的。
它可以同来表示类对象自身的意思当我们使用类对象调用方法的时候self会自动被python传入在方法内部想要访问类的成员变量必须使用self在传入参数时候self是透明的可以不用理会它
类和对象
** 什么是面向对象使用对象进行编程** 设计类基于类创建对象并使用对象来完成具体的工作
构造方法
Python类可以使用 init()方法称之为构造方法。 可以实现
在创建类对象构造器的时候 会自动执行在创建类对象构造器的时候将传入参数自动传递给__init__()使用
class Student:name Noneage Nonegender Nonedef __init__(self, name, age, gender):self.name nameself.age ageself.gender genderstu_1 Student(张三, 18, 女)# 获取对象中记录的信息
print(stu_1.name, stu_1.age, stu_1.gender) # 张三 18 女class Student:def __init__(self, name, age, gender):self.name nameself.age ageself.gender genderstu_1 Student(张三, 18, 女)# 获取对象中记录的信息
print(stu_1.name, stu_1.age, stu_1.gender) # 张三 18 女注意
构造方法也是成员方法不要忘记在参数列表中提供self在构造方法内定义成员变量需要使用self关键字 这是因为变量是在定义在构造方法内部如果要成为成员变量需要用self来表示
其他内容方法
魔术方法python把内置的类方法称之为魔术方法
init() 构造方法str() 字符串方法 当类对象需要被转换为字符串输出时会输入内存地址内存地址没有多大作用可以通过此方法控制类转换为字符串的行为 lt() 大于小于 符号比较 直接对两个对象进行比较是不可以的但是在类中实现__lt__方法即可同时完成小于大于两个符号比较 le() 小于等于大于等于符号比较 直接对两个对象进行比较是不可以的但是在类中实现__le__方法即可同时完成小于等于大于等于两个符号比较 eq() 符号比较 不实现__eq__方法对象之间可以进行比较但是比较内存地址即 不同对象比较一定是False结果实现__eq__方法就可以按照自己的想法来决定2个对象是否相等了
class Student:name Noneage Nonegender Nonedef __init__(self, name, age, gender):self.name nameself.age ageself.gender genderdef __str__(self):return f{self.name}:{self.age}:{self.gender}def __lt__(self, other):return self.age other.agedef __le__(self, other):return self.age other.agedef __eq__(self, other):return self.name other.namestu_1 Student(张三, 18, 女)
stu_2 Student(李四, 16, 男)
# 获取对象中记录的信息
print(stu_1.name, stu_1.age, stu_1.gender) # 张三 18 女
print(stu_1) # 张三:18:女
print(stu_1.__lt__(stu_2)) # False
print(stu_1.__le__(stu_2)) # False
stu_3 Student(李wu, 16, 男)
print(stu_2.__le__(stu_3)) # True
stu_4 Student(李四, 16, 男)
print(stu_2.__eq__(stu_4)) # True封装
面向对象编程是许多编程语言都支持的一种编程思想 基于模板类去创建实体对象使用对象完成功能开发 面向对象三大主要特性
封装继承多态
类中提供了私有成员的形式来支持
私有成员变量私有成员方法
定义私有成员的方式比较简单
私有成员变量变量名已__开头两个下划线私有成员方法变量名已__开头两个下划线
即可完成私有成员的设置
# 定义一个类包含私有成员变量和方法class Student:__name None__age Nonedef __change_name(self, name):self.__name namestu Student()
# stu.__name 张三 # 不报错
print(stu.__name) # 报错
#
stu.__change_name(Lisi) # 报错私有成员无法被类对象使用但是可以被其它的成员变使用
继承 class 类名(父类名) 类内容体 继承分为单继承和多继承继承表示将从父类那里继承来成员变量和成员方法不含私有
单继承
##############单继承
class Phone:IMEI Noneproducer HWdef call_by_4g(self):print(4g)class Phone2023(Phone):face_id 10001def call_by_5g(self):print(2023 5G)phone Phone2023()
print(phone.producer) # HW
print(phone.IMEI) # None
phone.call_by_4g() # 4g
phone.call_by_5g() # 2023 5G多继承
python的类之间也支持多继承即一个类也可以继承多个父类 语法 class 类名(父类1, 父类2, …, 父类N) 类内容体 ##############多继承
class Phone:IMEI Noneproducer HWdef call_by_4g(self):print(4g)class NFC:nfc_type 第五代producer HW2def read_card(self):print(nfc读卡)def write_card(self):print(nfc写卡)class RemoteControl:rc_type 红外def control(self):print(红外开启)class Phone2023(Phone, NFC, RemoteControl):pass #phone Phone2023()
print(phone.producer) # HW
print(phone.IMEI) # None
phone.call_by_4g() # 4g
phone.write_card() # nfc写卡
phone.read_card() # nfc读卡
phone.control() # 红外开启注意事项
单继承一个类继承一个类多继承一个类继承多个类按照顺序向左向右依次继承多继承中如果父类有同名方法或者属性先继承的优先级高于后继承
补充 pass是占位语句用来保证函数方法或者类定义的完整性表示无内容空的意思
复写
子类继承父类的成员属性和成员方法后如果对其不满意可以进行复写 即在子类中重新定义同名的属性或者方法即可
##############复写
class Phone:IMEI Noneproducer HWdef call_by_4g(self):print(4g)class Phone2023(Phone):producer XIAOMIdef call_by_4g(self):print(4g加速)phone Phone2023()
print(phone.producer) # XIAOMI
print(phone.IMEI) # None
phone.call_by_4g() # 4g加速调用父类同名成员 一旦复写父类成员那么类对象调用成员的时候就会调用复写后的新成员 如果需要使用被复写的父类的成员需要特殊的调用方式 方式1
调用父类成员 使用成员变量父类名.成员变量使用成员方法父类名.成员方法(selg)
方式2:
使用super()调用父类成员 使用成员变量super.成员变量使用成员方法super().成员方法()
注意只可以在子类内部调用父类的同名成员子类的实体类对象调用默认的是调用子类复写的
类型注解
变量的类型注解
基本语法变量类型 基本数据类型注解 var_1: int 10 var_2: float 20.2 var_3: bool True var_4: str “xxxx” 类对象注解 class student: pass stu: Student Student() 基础容器类型注解 my_list: list [1, 2, 3] my_tuple: tuple (1, 2, 3) my_set: set {1, 2, 3} my_dict: dict {“xxx”: 444} my_str: str “xxxxxxx” 容器类型详细注解 my_list: list[int] [1, 2, 3] my_tuple: tuple[str, int, bool] (“xxxx”, 1, True) my_set: set[int] {1, 2, 3} my_dict: dict[str, int] {“xxx”: 444} 注意
元组类型设置类型详细注解需要将每个元素都标记出来字典类型设置类型详细注解需要两个类型第一个是key第二个是value
除了使用变量 类型也可以在注释中进行类型注解 语法#type: 类型 在注释中进行类型注解 class Student: pass var_1 random.randint(1, 10) # type: int var_2 json.loads(data) # type: dict[str, int] var_3 func() # type: Student 为变量设置注解显示的变量定义一般无需注解一般无法直接看出变量类型之时会添加变量的类型注解
类型注解的主要功能
帮助第三方工具对代码进行类型的推断协助代码提示帮助开发者自身对变量进行类型注解
并不会真正对类型做验证和判断也就是类型注解仅仅是提示性的不是决定性的
函数方法的类型注解 函数和方法的形参类型注解语法 def 函数方法名(形参名: 类型, 形参名: 类型, …): pass 返回值注解: ddef 函数方法名(形参名: 类型, 形参名: 类型, …) - 返回值类型: pass Union类型 from typing import Union my_list: list[Union[str, int]] [1, 2, “xxxx”, “cccc”] my_dict: dict[str, Union[str, ing]] {“xxx”: “xxx”, “vvv”: 12} 可以使用Union[类型, …, 类型],可以定义联合类型注解 在函数方法注解形参和返回值 def func(data: Union[str, int]) - Union[str, int]: pass 多态
指的是多种状态即完成某个行为时使用不同的对象会得到不同的状态 多态常用在继承上 比如
函数方法形参声明接受父类对象实际传入父类的子类对象进行工作
即
以父类做定义声明以子类做实际工作用以获得同一行为不同状态
抽象类含有抽象方法的类称之为抽象类 抽象方法方法体是空实现pass称之为抽象方法
class Animal:def speak(self):passclass Dog(Animal):def speak(self):print(汪汪汪)class Cat(Animal):def speak(self):print(喵喵喵)这种设计的含义是
父类用来确定哪些方法具体的方法实现有子类自己决定
这种写法就叫抽象类也称之为接口 抽象类的作用
多用于顶层设计以便子类做具体实现也是对子类的一种软性约束要求子类必须复写实现父类的一些方法。并配合多态使用获得不同的工作状态
综合案例
python高级技巧
闭包
定义在函数嵌套的前提下内部函数使用了外部函数的变量并且外部函数返回了内部函数我们吧这个使用外部函数变量的内部函数称之为闭包。 简单的闭包
def outer(logo):def inner(msg):print(f{logo}{msg}{logo})return innerfn1 outer(ccc) # fn1就等于 inner方法
fn1(yyy) # cccyyyccc
fn1(hhh) # hhhyyyhhh
使用nonlocal关键字修饰外部函数的变量才可以在内部函数中修改它
def outer(num1):def inner(num2):nonlocal num1num1 num2print(num1)fn1 outer(10)
fn1(10) # 20
fn1(10) # 30闭包的好处和缺点
优点不定义全局变量也可以让函数持续访问和修改一个外部变量优点闭包函数引用的外部变量是外层函数的内部变量。作用域封闭难以被误操作修改缺点格外的内存占用
nonlocal关键字的作用 在闭包函数内部函数中想要修改外部函数的变量值需要使用nonlocal声明这个外部变量
装饰器
其实就是一种闭包其功能就是在不破坏目标函数原有的代码和功能的前提下为目标函数增加新功能
基础写法
def sleep():import randomimport timeprint(睡眠中)time.sleep(random.randint(1, 5))### 在调用前打印我要睡觉了 执行完成后打印我起床了
# 定义一个闭包函数在闭包方法函数内部
# 1. 执行目标函数
# 2. 并完成功能的添加def outer(func):def inner():print(我要睡觉了)func()print(我起床了)
fn outer(sleep)
fn()快捷写法
outer
def sleep():import randomimport timeprint(睡眠中)time.sleep(random.randint(1, 5))### 在调用前打印我要睡觉了 执行完成后打印我起床了
# 定义一个闭包函数在闭包方法函数内部
# 1. 执行目标函数
# 2. 并完成功能的添加def outer(func):def inner():print(我要睡觉了)func()print(我起床了)sleep()设计模式
单例模式
## 工具类包
class strTools:passstr_tool StrTools()# 引用文件
from test import str_tools1 str_tool
s2 str_tool
## 同一个对象多线程
threading模块 import time
import threadingdef sing():while True:print(我在唱歌)time.sleep(1)def dance():while True:print(我在跳舞)time.sleep(1)if __name__ __main__:sing_thread threading.Thread(targetsing, name唱歌线程)dance_thread threading.Thread(targetdance, name跳舞线程)sing_thread.start()dance_thread.start()import time
import threadingdef sing(msg):while True:print(msg)time.sleep(1)def dance(msg):while True:print(msg)time.sleep(1)if __name__ __main__:sing_thread threading.Thread(targetsing, name唱歌线程, args(我在唱歌,))dance_thread threading.Thread(targetdance, name跳舞线程, kwargs{msg: 我在跳舞})sing_thread.start()dance_thread.start()
网络编程
正则表达式
递归
https://flet.dev/docs/guides/python/getting-started
peewee 学习python轻量级操作ORM框架
fastAPI 学习python轻量级API框架
PydanticStarlette和FastApi的关系
Pydantic是一个基于Python类型提示来定义数据验证序列化和文档使用JSON模式库Starlette是一种轻量级的ASGI框架/工具包是构建高性能Asyncio服务的理想选择
from datetime import datetime, date
from typing import List, Optionalfrom pydantic import BaseModel, ValidationError
Data validation and settings management using python type annotations
使用python的类型注解来进行数据校验和setting管理pydantic 可以在代码运行时提供类型提示数据校验失败时提供友好的错误提示定义数据应该如果在纯规范的python代码中保存并用pydantic验证它
class User(BaseModel):id: int # 必填字段name: str xxxx # 有默认值选填字段signup_ts: Optional[datetime] Nonefriends: List[int] [] # 列表中元素使int类型或者可以直接转换成int类型 “1”external_data {id: 123,signup_ts: 2023-12-12 12:22,friends: [1, 2, 3]
}user User(**external_data)
print(user.id, user.name, user.signup_ts, user.friends)
print(repr(user.signup_ts)) # __repr__主要用于调试和开发而__str__用于为最终用户创建输出。 __repr__打印datetime.datetime(2023, 12, 12, 12, 22)
print(dict(user))# ------------------- 校验失败处理
try:User(id1, signup_tsdatetime.today(), friends[1, 2, not number])
except ValidationError as e:print(e.json())# --------------------------模型类的属性和方法
print(user.dict)
print(user.json)
print(user.copy) # 这里是浅拷贝
# print(user.parse_obj(objexternal_data))
# print(user.parse_raw())class Sound(BaseModel):sound: strclass Dog(BaseModel):birthday: dateweight: float Optional[None]sound: List[Sound]
快速上手
# 文件名称main.py
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModelapp FastAPI()class Item(BaseModel):name: strprice: floatis_offer: Optional[bool] Noneapp.get(/)
def read_root():return {Hello: World}app.get(/items/{item_id}) # q为后面参数 /item/1?qxxx
def read_item(item_id: int, q: Optional[str] None):return {item_id: item_id, q: q}app.put(/items/{item_id})
def update_item(item_id: int, item: Item): # item json参数return {item_name: item.name, item_id: item_id}######启动命令uvicorn main:app --reload # --reload 修改内容服务器会重载路径参数和数据的解析验证
from datetime import date
from enum import Enum
from typing import Optional, List
from pydantic import BaseModel, Field
from fastapi import APIRouter, Path, Query, Cookie, Header # path 校验路径参数用app03 APIRouter()
路径参数和数字验证
app03.get(/path/parameters)
def path_params01():return {message: This is a message}app03.get(/path/{parameters})
def path_params01(parameters: str): # 函数的顺序就是路由的顺序return {message: parameters}class CityName(str, Enum):BEI_JING beijing chinaSHANG_HAI shanghai chinaapp03.get(/enum/{city})
async def latest(city: CityName):if city CityName.SHANG_HAI:return {city_name: city, confirmed: 1492, death: 7}if city CityName.BEI_JING:return {city_name: city, confirmed: 971, death: 9}return {city_name: city, latest: unknown}app03.get(/files/{file_path:path}) # 通过path parameters传递文件路径 添加:path 表示file_path有/ 不作为路径而是文件路径参数
def print_file_path(file_path: str):return fthe file_path is {file_path}app03.get(/path_num/{num})
def path_params_validate(num: int Path(None, ge1, le10, title你的数字参数, description不可描述)):return num查询参数和数据的解析和验证 查询参数和数据的解析。验证
app03.get(/query)
def page_limit(page: int 1, limit: Optional[int] None): # 给了默认值就是选填的参数if limit:return {page: page, limit: limit}return {page: page}app03.get(/query/bool/conversion)
def type_conversion(param: bool False): # bool类型转换yes on 1 True 会转换成Truereturn paramapp03.get(query/validations)
def query_params_validate(value: str Query(..., min_length8, max_length16, regex^a),values: List[str] Query(default[v1, v2], aliasalias_name)):return values, value
请求体以及混合参数 请求体和字段
class CityInfo(BaseModel):name: str Field(..., examplebeijing) # example是注解的作用值不会被认证country: strcountry_code: str None # 给定一个默认值country_population: int Field(default800, title人口数量, description国家的人口数量, ge800)class config:schema_extra {example: {name: beijing,country: china,country_code: CN,country_population: 140000000}}app03.post(/request_boby/city)
def city_info(city: CityInfo):print(city.name, city.country, city.country_code, city.country_population)return city.model_dump_json()
请求体以及混合参数 多参数混合
app03.post(/query_city/{name})
def mix_city_info(name: str,city01: CityInfo,city02: CityInfo,confirmed: int Query(ge0, description确诊数, default0),death: int Query(ge0, description死亡数, default0)
):return city01.model_dump_json(), city02.model_dump_json()
如何定义数据格式嵌套的请求体 数据格式嵌套的请求体
class Data(BaseModel):city: List[CityInfo] None # 这里是定义数据格式嵌套的请求体data: date # 额外的数据类型还有uuiddatetime, bytes, frozenset,confirmed: int Field(ge0, description确诊数, default0)deaths: int Field(ge0, description死亡数, default0)recovered: int Field(ge0, description死亡数, default0)app03.post(/query_body/nested)
def nested_models(data: Data):return data
如何设置Cookie和Header参数 Cookie 和 Header 参数app03.get(/cookie)def cookie(cookie_id: Optional[str] Cookie(None)): # 定义cookie参数需要使用到Cookie类return {cookie_id: cookie_id}app03.get(/header)
def header(user_agent: Optional[str] Header(None, convert_underscoresTrue),x_token: List[str] Header(None, convert_underscoresTrue)): # convert_underscores 表示是否转换下划线 user_agent -- userAgentreturn {header: user_agent,x_token: x_token}
Asynico学习
协程
**概念**在同一线程内一段执行代码过程中可以中断并跳转到另一端代码中接着之前中断的地方继续执行协程运行状态于多线程类似。 协程优点
无需线程上下文切换协程避免了无意义的调度可以提高性能无需原子操作锁定及同步开销方便切换控制流简化编程模型高并发 高扩展 低成本 一个CPU支持上万的协程不是问题很适合用于高并发处理
协程缺点
无法利用多核资源协程本质是单线程不是同时将单个CPU的多个核用上协程需要进程配合才能运行在CPU上进行阻塞操作如IO时会阻塞整个程序
实现协程的办法
greenlet, 早期模块yield 关键字
# def func():
# print(当前是一个生成器函数)
# while True:
#
# 下面没有代码会暂停下一次运行的时候接着上一次运行的位置继续运行
#
# yield 这是生成器函数返回的数据。。。
#
#
# obj func() # 返回一个对象生成器对象
# print(obj) # generator object func at 0x000001F85DF34F40generator object func at 0x000001F85DF34F40
# print(next(obj)) # 生成器需要通过next()方法进行驱动
中断暂停的特点
在运行第一个任务的使用遇到yield暂停并切换到另一个任务上继续执行
# 利用生成器特性进行任务切换
import timedef func_a():while True:print(这是func_a函数)yield time.sleep(0.5)def fun_b(obj):while True:print(这是func_b)obj.__next__()a func_a()
fun_b(a)asyncio修饰器
import asyncioasyncio.coroutine
def func1():print(1)yield from asyncio.sleep(2) # 遇到IO耗时自动化切换到tasks中的其他任务print(2)asyncio.coroutine
def func2():print(3)yield from asyncio.sleep(2) # 遇到IO耗时自动化切换到tasks中的其他任务print(4)tasks [asyncio.ensure_future(func1()),asyncio.ensure_future(func2())
]loop asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
anync, await
import asyncio
import timeasync def say_after(delay, what):await asyncio.sleep(delay)print(what)async def main():print(fstarted at {time.strftime(%X)})await say_after(1, hello)await say_after(2, world)print(ffinished at {time.strftime(%X)})asyncio.run(main())同步程序与异步程序的执行对比
同步先执行第一个事务如果遇到阻塞则进行等待知道一个事务执行完毕在执行第二个事务
def func():time.sleep(1)now lambda: time.time()
start now()for i in range(5):func()print(同步所花费的诗句%f s % (now() - start))### 同步所花费的诗句5.002251 s
异步执行第一个事务之后如果遇到阻塞则会执行第二个事务不会等待可以通过状态通知回调来调用处理结果
async def func(x):await asyncio.sleep(1)print(x)for i in range(5):asyncio.run(func(i))print(异步所花费的诗句%f s % (now() - start))
Asynic事件循环
理解成一个死循环去检测并执行某些代码
任务列表 [任务1, 任务2, 任务3, ...]while True:可执行的任务列表已完成的任务列表去任务列表中检查所有的任务将可执行和已完成的任务返回for 就绪任务 in 可执行的任务列表:执行已就绪的任务for 完成任务 in 已完成的任务列表:在任务列表中移除已完成任务如果任务列表中的任务都已完成则终止循环
import asyncio# 去生成或获取一个事件循环
loop asyncio.get_event_loop()
# 将任务放到任务列表中去
loop.run_until_complete(任务)快速上手 async
协程函数定义函数时候async def 函数名 协程对象执行协程函数() 得到的协程 对象
async def func():passresult func()注意执行协程函数创建协程对象函数内部代码不执行 如果想要运行协程函数内部代码必须要讲协程对象交给事件循环来处理
import asyncioasync def func():print(111)result func()
# 去生成或获取一个事件循环
loop asyncio.get_event_loop()
# 将任务放到任务列表中去
loop.run_until_complete(result)await
await 可等待对象协程对象FutureTask对象 - IO等待
import asyncioasync def func():print(1111)response await asyncio.sleep(2)print(结束, response)asyncio.run(func())import asyncioasync def others():print(start)await asyncio.sleep(2)print(end)return 返回值async def func():print(执行协程函数内部代码)# 遇到IO操作挂起当前协程任务 等待IO操作完成之后再继续往下执行当前协程挂起时事件循环可以去执行其他协程(任务)response await others()print(IO请求结果结束结果, response)asyncio.run(func())await就是等待对象的值得到结果之后再继续往下走
Task对象
在事件循环中添加多个任务 Tasks用于并发调度协程通过asyncio.create_task(协程对象)的方式来创建Task对象这样可以让协程加入事件循环中等待被调度执行除了使用了asyncio.create_task()函数外还可以使用低层级的loop.create_task()或者ensuer_future函数不建议手动实例化Task对象 import asyncioasync def others():print(start)await asyncio.sleep(2)print(end)return 返回值async def func():print(执行协程函数内部代码)# 遇到IO操作挂起当前协程任务 等待IO操作完成之后再继续往下执行当前协程挂起时事件循环可以去执行其他协程(任务)response await others()print(IO请求结果结束结果, response)async def main():print(main开始)# 创建Task对象将当前执行func函数任务添加到事件循环task1 asyncio.create_task(func())task2 asyncio.create_task(func())print(main结束)# 当执行某协程遇到的IO操作时会自动化切换执行其他任务# 此处的await是等待相对应的协程全部执行完毕并获取结果result await task1resule2 await task2print(result, resule2)asyncio.run(main())import asyncioasync def others():print(start)await asyncio.sleep(2)print(end)return 返回值async def func():print(执行协程函数内部代码)# 遇到IO操作挂起当前协程任务 等待IO操作完成之后再继续往下执行当前协程挂起时事件循环可以去执行其他协程(任务)response await others()print(IO请求结果结束结果, response)async def main():print(main开始)task_list [asyncio.create_task(func(), nametask1),asyncio.create_task(func(), nametask2)]print(main结束)done, pending await asyncio.wait(task_list, timeoutNone) # done 收到一个已经完成的集合pending是没有完成的集合print(done, pending)asyncio.run(main())import asyncioasync def others():print(start)await asyncio.sleep(2)print(end)return 返回值async def func():print(执行协程函数内部代码)# 遇到IO操作挂起当前协程任务 等待IO操作完成之后再继续往下执行当前协程挂起时事件循环可以去执行其他协程(任务)response await others()print(IO请求结果结束结果, response)task_list [func(),func()
]done, pending asyncio.run(asyncio.wait(task_list))
print(done)
Future对象
Task是继承Future Task对象内部await结果的处理基于Future对象来的
import asyncioasync def main():# 获取当前循环事件loop asyncio.get_running_loop()# 创建一个任务Future对象这个任务什么都不干fut loop.create_future()# 等待任务最终结果没要结果则会一直等下去await futasyncio.run(main())import asyncioasync def set_after(fut):await asyncio.sleep(2)fut.set_result(6666)async def main():# 获取当前循环事件loop asyncio.get_running_loop()# 创建一个任务Future对象这个任务什么都不干fut loop.create_future()# 创建一个任务Task对象绑定了set_after函数函数在内部2s之后会给fut赋值# 即手动设置future任务的最终结果那么fut就可以结束了await loop.create_task(set_after(fut))# 等待任务最终结果没要结果则会一直等下去date await futprint(date)asyncio.run(main())concurrent.futures.Future对象
使用线程池进程池实现异步操作时用到的对象
import time
from concurrent.futures.thread import ThreadPoolExecutordef func(value):time.sleep(1)print(value)pool ThreadPoolExecutor(max_workers5)
# 或者 ProcessPoolExecutor(max_workers5)for i in range(10):fut pool.submit(func, i)print(fut)启动调用顺序连接加载日志显示群组显示新功能页面项目封装