PythonLearn

简单数据类型

数据类型转换

int(x) float(x) str(x) chr(x) ord(x) hex(x) oct(x) bin(x)

eval函数

Python中的内置函数, 用于去掉字符串最外侧的引号, 并按照逻辑运算

age=eval(input('请输入年龄:'))#将input读入的字符串类型转成了int类型,相当于int(age)
print(age,type(age)) #18 

hello='北京欢迎你'
print(hello)#北京欢迎你
print(eval('hello'))#北京欢迎你

算术运算符

/  除法--5/2=2.5
// 整除--5/2=2
%  取余--5%2=1

赋值运算符

/=  除赋值   x/=y x=x/y
%=  取余赋值 x%=y x=x%y
**= 幂赋值   x**=y x=x**y
//= 整除赋值 x//=y x=x//y

程序逻辑控制

选择结构

if 表达式1:
    语句块1
elif 表达式2:
    语句块2
else:
    语句块3

模式匹配

macth score:
    case 'A':
        code1
    case 'B':
        code2
    case 'C':
        code3

循环for…else…结构

for 循环变量 in 遍历对象:
    code1
else:
    code2#循环正常结束后执行code2, 异常退出/break不会执行code2

while…else…结构

while exp1:
    code1
else:
    code2

空语句pass

pass是Python中的保留字, 在语法结构中只起到占位符作用使语法完整不报错, 一般可用在if, for, while, 函数打定义, 类的定义中

组合数据类型

列表

指一系列按特定顺序排列的元素组成,是Python中内置的可变序列,使用[]定义列表,元素与元素之间使用英文逗号分隔, 列表中的元素可以是任意的数据类型

lst.append(x)
lst.insert(index,x)
lst.clear()
lst.pop(index)
lst.remove()
lst.reserve(x)
lst.copy()
列表排序的两种方式
1.列表对象的sort方法
lst.sort(Key,reverse)
2.内置的sorted()
new_lst=sorted(lst)#产生新的列表对象

列表生成式

lst=[for item in range(1,11) if item%2==0]#example

二维列表

lst=[
    [],
    [],
    []
]
lst=[[j for j in range(5)]for i in range(4)]

for row in lst:
    for i in row:
    	code1
    code2

元组

是python中内置的不可变序列,使用()定义元组,元素与元素之间使用英文的逗号分隔,元组中只有一个元素的时候,逗号也不能省略

元组的创建

t=('hello',10,1)
t=tuple('123')#('1','2','3')

元组的遍历

for item in t:
for item in range(len(t)):
for index,item in enumerate(t):

字典

是根据一个信息查找另一个信息的方式构成了’键值对’, 它表示索引用的键和对应的值构成的成对关系, 不可变序列

字典的创建

d={1:'miao',2:'cat'}#1
lst1=[1,2,3,4]#2
lst2=['cat','dog','pig']
zip_obj=zip(lst1,lst2)
d2=dict(zip_obj)
d3=dict(cat=1,dog=2)#3

字典取址

d[key]
d.get(key)

字典生成式

d={item : random.randint(1,100) for item in range(1,4)}

集合

是Python中的集合,与数学中集合的概念一致, Python中的集合是一个无序的不重复元素序列, 集合只存储不可变数据类型, 用{}定义, 是Python中的可变数据类型

集合的创建

s={20,30,10,3}
print(s)
s=set()
print(type(s))#

集合的操作符

s={20,30,10,'3'}
s2=set('35')
print(s^s2,s&s2,s|s2,s-s2)

集合生成式

s={i for i in range(1,10)}
for index,i in enumerate(s):
    print(index,i)

字符串及正则表达式

字符串是Python中的不可变数据类型

字符串常用操作

str.lower()
str.upper()
str.split(sep='')
str.count(s)
str.find(s)
str.index(s)
str.startWith(s)
str.endwith(s)
s='HelloWorld'
print(s.lower())
print(s.upper())
print(s.replace('o','11',1))#Hell11World

格式化字符串

name='Tom'
age=18
score=200
print('姓名:%s,年龄:%d,分数:%.1f'%(name,age,score))#占位符
print(f'name:{name},age:{age},score:{score}')#f-string
print('name:{0},age:{1},score:{2}'.format(name,age,score))#.format

数据的验证

str='12345'
print(str.isdigit())
print(str.isnumeric())
print(str.isalpha())
print(str.isalnum())
print(str.islower())

字符串拼接

s1='hello'
s2='world'
print(s1+s2)
print('*'.join([s1,s2]))
#格式化拼接

正则表达式

基本匹配
. : 匹配任何单个字符(除了换行符)。
^ : 匹配字符串的开始。
$ : 匹配字符串的结束。
字符集和范围
[abc] : 匹配字符a、b或c中的任何一个。
[^abc] : 匹配除了a、b、c以外的任何字符。
[0-9] : 匹配一个数字(09)。
[a-z] : 匹配一个小写字母。
[A-Z] : 匹配一个大写字母。
[a-zA-Z] : 匹配一个字母(大小写都行)。
预定义字符类
\d : 匹配一个数字(等价于[0-9])。
\D : 匹配一个非数字字符(等价于[^0-9])。
\w : 匹配一个字母、数字或下划线(等价于[a-zA-Z0-9_])。
\W : 匹配一个非字母、数字或下划线的字符。
\s : 匹配任何空白字符(如空格、制表符、换行符)。
\S : 匹配任何非空白字符。
常见用法
re.match(): 从字符串的起始位置开始匹配正则表达式。如果字符串的开始部分符合正则表达式,则返回一个匹配对象,否则返回None。
re.search(): 在整个字符串中搜索第一个匹配的正则表达式,返回一个匹配对象。
re.findall(): 返回字符串中所有匹配正则表达式的部分,返回的是一个列表。
re.sub(): 替换字符串中匹配正则表达式的部分。
re.split(): 根据正则表达式将字符串分割成多个部分,返回一个列表。

异常处理

try:
    num1=int(input())
    num2=int(input())
    result=num1 / num2
    print(result)
except ZeroDivisionError:
    print('除数不能为0')
except ValueError:
    print('输入错误')
except BaseException:
    print('未知异常')
try:
    gender=input()
    if gender!=0 and gender!=1:
        raise Exception('error gender')
    else:
        print(gender)
except Exception as e:
    print('error')

常见异常类型

TypeError:类型错误。
ValueError:值错误。
NameError:名称错误。
IndexError:索引错误。
KeyError:键错误。
ZeroDivisionError:除零错误。
IOError:输入输出错误。
ImportError:导入错误。
AttributeError:属性错误。
KeyboardInterrupt:键盘中断。

函数

函数是将一段实现功能的完整代码使用函数名称进行封装, 通过函数名称进行调用, 以达到一次编写多次调用的目的

def get_sum(n):
    s=0
    for i in range(1,n+1):
        s+=i
    return s

s=get_sum(7)
print(s)
#个数可变的位置参数
def fun(*para):
    print(type(para))
    for i in para:
        print(i)
fun(1,2,3,4)# 1 2 3 4
fun(1)# 1
#个数可变的关键字参数
def fun2(**para):
    print(type(para))
    for key,value in para.items():
        print(key,value)

fun2(name='Tom',age=18,gender=1)# name Tom age 18 gender 1

变量的作用域

指变量起作用的范围, 根据范围作用的大小可分为局部变量和全局变量

匿名函数lambda

指没有名字的函数,这种函数只能使用一次, 一般是在函数的函数体只有一句代码且只有一个返回值时, 可以使用匿名函数来简化

result=lambda 参数列表:表达式
result=lambda a,b:a+b
print(result(1,3))

递归函数

def func(n):
    if n==1:
        return 1
    else:
        return n*func(n-1)
print(func(3))

内置的常用函数

format(value,format_spec)#将value以format_spec格式进行显示
len(s)
id(obj)#获取对象的内存地址
type(x)
eval(s)

format_spec内置的常用数学函数

abs(x)
divmod(x,y)
max(sequence)
min(sequence)
sum(iter)
pow(x,y)
round(s,d)

内置的常用迭代器操作函数

sorted(iter)
reversed(sequence)
zip(iter1,iter2)
enumerate(iter)
all(iter)
any(iter)
next(iter)
filter(function,iter)#通过指定条件过滤序列并返回一个迭代器对象
map(function,iter)#通过函数function对可迭代对象iter的操作返回一个迭代器对象

类和对象

自定义数据类型的语法结构为

class 类名():
    pass
#创建对象的语法格式为:
对象名=类名()

类的组成

类属性, 实例属性, 实例方法, 静态方法, 类方法

class Student():
    #类属性
    school='北京大学'
    #初始化方法
    def __init__(self,xm,age):
        self.name=xm #左侧是实例属性,xm是局部变量, 将局部变量的值xm赋值给实例属性
        self.age=age
    #类中的函数称为方法,自带一个参数self的为实例方法
    def show(self):
        print(f'name:{self.name},age:{self.age}')
    #静态方法
    @staticmethod
    def sm():
        print('a static method,不能调用实例属性,也不能调用实例方法')
    #类方法
    @classmethod
    def cm(cls):
        print('a class method,不能调用实例属性,也不能调用实例方法')
s=Student('Tom',18)#创建类的对象
#实例属性,使用对象名进行打点调用的
print(s.name,s.age)
#类属性,直接使用类名打点调用
print(Student.school)
#实例方法,使用对象名进行打点调用
s.show()
#类方法使用类名打点调用
Student.cm()
#静态方法,使用类名打点调用
Student.sm()

面向对象的三大特征

#封装
class Student():
    def __init__(self,name,age,gender):
        self._name=name #左侧是实例属性,xm是局部变量, 将局部变量的值xm赋值给实例属性
        self.__age=age
        self.gender=gender
    def _fun(self):
        print('子类及本身可以访问')
    def __fun2(self):
        print('只有定义的类可以访问')
    def show(self):
        self._fun()
        self.__fun2()
        print(self._name)
        print(self.__age)

stu=Student('Tom',20,'女')
stu.show()
print(stu._Student__age)#20
stu._Student__fun2()#只有定义的类可以访问
class Student():
    def __init__(self,name,gender):
        self.name=name
        self.__gender=gender

    @property#使用@property修改方法, 将方法转成属性使用
    def gender(self):
        return self.__gender
    @gender.setter#将gender属性设置为可写属性
    def gender(self,value):
        if value != '男' and value !='女':
            print('default set man')
            self.__gender='男'
        else:
            self.__gender=value
s=Student('Tom','男')
print(s.gender)
s.gender='女'
print(s.gender)
#继承的语法结构
class 类名(父类1,父类2...,父类N)
class Person:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def show(self):
        print(f'name:{self.name},age:{self.age}')

#子类
class Student(Person):
    def __init__(self,name,age,stuno):
        super().__init__(name,age)
        self.stuno=stuno

class Doctor(Person):
    def __init__(self,name,age,dep):
        super().__init__(name,age)
        self.dep=dep

#实例
s=Student('Tom',10,'1001')
s.show()
d=Doctor('Amy',30,'外科')
d.show()
#Python中一个子类也可以继承多个父类
class FatherA:
    def __init__(self,name):
        self.name=name
    def showA(self):
        print('in FatherA')
class FatherB:
    def __init__(self,age):
        self.age=age
    def showB(self):
        print('in FatherB')
class Son(FatherB,FatherA):
    def __init__(self,name,age,gender):
        FatherA.__init__(self,name)
        FatherB.__init__(self,age)
        self.gender=gender

son=Son('Tom','女',18)
son.showB()
son.showA()
#多态-指的是多种形态, 即便不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用对象的方法
class Person:
    def eat(self):
        print('person eat')
class Cat:
    def eat(self):
        print('cat eat')
class Dog:
    def eat(self):
        print('dog eat')
def func(obj):
    obj.eat()

p=Person()
c=Cat()
d=Dog()
func(p)#person eat
func(c)#cat eat
func(d)#dog eat
#特殊属性
obj._dict_对象的属性字典
obj._class_对象所属的类
class._bases_类的父类元组
class._base_类的父类
class._mro_类的层次结构
class._subclasses_()类的子类列表

类的深拷贝与浅拷贝

#变量的赋值
class Cpu():
    pass
class Disk():
    pass
class Computer():
    def __init__(self,cpu,disk):
        self.cpu=cpu
        self.disk=disk
cpu=Cpu()
disk=Disk()
com=Computer(cpu,Disk)
com1=com
print(com,com1)#<__main__.Computer object at 0x000002D609C41E10> <__main__.Computer object at 0x000002D609C41E10>
print(com.disk,com1.disk)# 
print(com.cpu,com1.cpu)#<__main__.Cpu object at 0x000002886D891D90> <__main__.Cpu object at 0x000002886D891D90>
#浅拷贝--拷贝时对象包含的子对象内容不开被, 源对象与拷贝对象引用同一个子对象
#深拷贝--使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象与拷贝对象所有的子对象也不相同
import copy
com2=copy.copy(com)#浅拷贝
com2=copy.deepcopy(com)#深拷贝

模块

PYthon中一个后缀名为.py的文件就是一个模块, 模块中可以定义函数,类等, 模块也可以避免函数,类,变量等名称相冲突的问题, 提高代码的可维护性可重用性; 在给模块命名的时候要求全部使用小写字母, 多个单词之间使用下划线进行分隔; 如果自定义模块与内置文件相同,会优先导入自定义模块

自定义模块规范代码, 将功能相同的函数, 类等封装到一个模块中, 可以被其他模块调用, 提高开发的效率

模块的导入

# import demo01 as d
# d.func()

from demo01 import name
print(name)

含有_init_.py文件的目录即为包, 可以避免模块名称相冲突的问题

Python中常用的内置模块

os模块,与操作系统和文件相关操作有关的模块
re模块,用于在Python的字符串中执行正则表达式的模块
random模块,用于产生随机数的模块
json模块,用于对高维数据进行编码和解码的模块
time模块, 与时间相关的模块
datetime模块,与日期时间相关的模块,可以方便的先是日期并对日期进行运算

第三方模块的安装与卸载

pip install 模块名称
import requests
import re
url='https://www.weather.com.cn/weather1d/101010100.shtml'#爬虫打开的浏览器上的网页
resp=requests.get(url)
resp.encoding='utf-8'
# print(resp.text)#resp响应对象,
city=re.findall('([\u4e00-\u9fa5]*)',resp.text)
weather=re.findall('([\u4e00-\u9fa5]*)',resp.text)
wd=re.findall('(.*)',resp.text)
zs=re.findall('([\u4e00-\u9fa5]*)',resp.text)
lst=[]
for a,b,c,d in zip(city,weather,wd,zs):
    lst.append([a,b,c,d])
for item in lst:
    print(item)
# print(city)
# print(weather)
# print(wd)
# print(zs)

'''
三亚
多云
29/20℃
适宜
'''
import requests
url='https://i.i8tq.com/adImg/rb2024/pc_index.jpg?0220'
resp=requests.get(url)
with open('logo.png','wb')as file:
    file.write(resp.content)

常用的第三方模块

#openpyxl模块, 适用于处理Microsoft Excel文件的第三方库, 可以对Excel文件中的数据进行写入和读取
load_workbook(filename)#打开已存在的表格, 结果为工作簿对象
workbook.sheetnames#工作簿对象的sheetnames属性, 用于获取所有工作表的名称, 结果为列表类型
sheet.append(lst)#向工作表中添加一行数据, 新数据在工作表已有数据的后面
workbook.save(excelname)#保存工作簿
Workbook()#创建新的工作簿对象
--------------------------------
import demo05
import openpyxl
html=demo05.get_html()
lst=demo05.parse_html(html)
workbook=openpyxl.Workbook()
sheet=workbook.create_sheet('景区天气')
for item in lst:
    sheet.append(item)
workbook.save('景区天气.xlsx')
----------------------------------
import openpyxl
workbook=openpyxl.load_workbook('景区天气.xlsx')
sheet=workbook['景区天气']
lst=[]
for row in sheet.rows:
    sub_lst=[]
    for cell in row:
        sub_lst.append(cell.value)
    lst.append(sub_lst)
for i in lst:
    print(i)
#Numpy模块--是Python数据分析方向和其他库的依赖库, 用于处理数组,矩阵等数据
#Pandas是基于Numpy模块扩展的一个数据分析模块, 使用Pandas读取Excel数据更方便
#Matploylib是用于数据可视化的模块,使用Matplotlib.pyplot可以绘制饼图,柱形图,折线图等
---------------------------------------
import matplotlib.pyplot as plt
import pandas as pd

df=pd.read_excel('excel')
plt.rcParams['font.sans-serif']=['SimHei']
plt.figure(figsize=(10,6))
labels=df['商品名称']
y=df['出库量']
# print(labels)
# print(y)
#绘制饼图
plt.pie(y,labels=labels,autopct='%1.1f%%',startangle=90)
#设置xy轴刻度
plt.axis('equal')
plt.title('饼图')
plt.show()
#pyEcharts是由百度开源的数据可视化库, 对流行图的支持度比较高, 它给用户提供了30多种图形, 如柱形渐变图,K线周期图等net: pyecharts.org
#PIL适用于图像处理的第三方库, 支持图像存储,处理和显示等操作 pip install pillow
#jieba是Python中用于对中文进行分词的模块, 可以将一段中文文本分割成中文词组的序列
#PyInstaller第三方库, 可以在Windows操作系统中将Python源文件打包成.exe的可执行文件, 还可以在Linux和MacOS操作系统中对源文件进行打包操作

文件IO

文件的基本操作

r,rb,w,wb,a,+
file.read(size)
file.readline(size)
file.wirte(s)
file.wirtelines(lst)
file.seek(offset)
#with语句, 又称上下文管理器, 在处理文件时, 无论是否产生异常都能保证with语句执行完毕后关闭已经打开的文件,这个过程是自动的无需手动操作
with open(...) as file:
    pass
-----------------------------
def write_fun():
    with open('aa.txt','w',encoding='utf-8') as file:
        file.write('welcome9')
def read_fun():
    with open('aa.txt','r',encoding='utf-8') as file:
        print(file.read())
def copy(src_file,target_file):
    with open(src_file,'r',encoding='utf-8') as file:
        with open(target_file,'w',encoding='utf-8') as file2:
            file2.write(file.read())

if __name__ == '__main__':
    write_fun()
    read_fun()
    copy('./aa.txt','./dd.txt')

数据的组织维度

#也成为数据的组织方式或存储方式, 在Python中查那个用的数据组织方式可分为一维数据,二维数据和高维数据
----------------------------------------------------
#存储和读取一维数组
def my_write():
    lst=['a','b','c','d','张三']
    with open('student.csv','w',encoding='utf-8') as file:
        file.write(' '.join(lst))

def my_write_table():
    lst=[
        ['商品','单价','数量'],
        ['a','10','2'],
        ['b','20','11'],
        ['c','18','8']
    ]
    with open('table.csv','w',encoding='utf-8') as file:
        for i in lst:
            line=','.join(i)
            file.write(line)
            file.write('\n')

if __name__ == '__main__':
    # my_write()
    my_write_table()
#json模块的常用函数
json.dumps(obj)#将Python数据类型转成JSON格式过程,编码过程
json.loads(s)#将JSON格式字符串转成Python数据类型, 解码过程
json.dump(obj,file)#与dumps()功能相同,将转换结果存储到文件file中
json.load(file)#与loads()功能相同,从文件file中读入数据

网络编程

TCP and UDP

Socket对象的常用方法

bind(ip,port)#绑定IP地址和端口
listen(N)#开始TCP监听,N表示操作系统挂起的最大连接数量,取值范围1-5之间,一般设置为5
accept()#被动接收TCP客户端连接,阻塞式
connect((ip,port))#主动初始化TCP服务器连接
recv(size)#接收TCP数据,返回值为字符串类型,size表示要接收的最大数据量
send(str)#发送TCP数据,返回值是要发送的字节数量
sendall(str)#完整发送TCP数据,将str中的数据发送到连接的套接字,返回之前尝试发送所有数据,如果成功为None,失败抛出异常
recvfrom()#接收UDP数据,返回值为一个元组(data,address),data表示接收到数据,address表示发送数据的套接字地址
sento(data,(ip,port))#发送UDP数据,返回值是发送的字节数
close()#关闭套接字

TCP

#服务器端
from socket import socket,AF_INET,SOCK_STREAM
#创建socket对象
server_socket=socket(AF_INET,SOCK_STREAM)
ip='127.0.0.1'
port=8888
#绑定ip地址和端口
server_socket.bind((ip,port))
server_socket.listen(5)
print('server start')
#等待客户端连接
client_socket,client_address=server_socket.accept()
#接收来自客户端数据
data=client_socket.recv(1024)
print('data:',data.decode('utf-8'))
#关闭socket
server_socket.close()
------------------------------------------
#客户端
import socket
#创建socket对象
client_socket=socket.socket()
#向服务器发送连接请求
ip='127.0.0.1'
port=8888
client_socket.connect((ip,port))
print('success connect')
#发送数据
client_socket.send('send a msg'.encode('utf-8'))
#关闭
client_socket.close()
print('发送完毕')

UDP

#发送方
import socket
#创建socket对象
client_socket=socket.socket()
#向服务器发送连接请求
ip='127.0.0.1'
port=8888
client_socket.connect((ip,port))
print('success connect')
#发送数据
client_socket.send('send a msg'.encode('utf-8'))
#关闭
client_socket.close()
print('发送完毕')
--------------------------------------
#接收方
from socket import socket,AF_INET,SOCK_DGRAM
recv_socket=socket(AF_INET,SOCK_DGRAM)
recv_socket.bind(('127.0.0.1',8888))
recv_data,addr=recv_socket.recvfrom(1024)
print('receive data:',recv_data.decode('utf-8'))
data=input('reply data')
recv_socket.sendto(data.encode('utf-8'),addr)
recv_socket.close()

进程与线程

创建进程的方式

#函数式创建子进程
Process(group=None,target,name,args,kwargs)
---------------------------
import os,time
from multiprocessing import Process

def test():
    print(f'this is a subProcess,my pip is {os.getpid()}, my origin process is {os.getppid()}')
    time.sleep(1)
if __name__ == '__main__':
    print('this is main process')
    lst=[]
    for i in range(5):
        p=Process(target=test)
        p.start()
        lst.append(p)
    for i in lst:
        i.join()#阻塞子进程
    print('main process end')
#继承式创建子进程
class 子进程(Process):
    pass
----------------------------------
from multiprocessing import Process
import os,time
class SubProcess(Process):
    def __init__(self,name):
        super().__init__()
        self.name=name
    def run(self):
        print(f'子进程的名称{self.name},PID:{os.getpid()},父进程PID:{os.getppid()}')

if __name__ == '__main__':
    print('主进程开始执行')
    lst=[]
    for i in range(5):
        p1=SubProcess(f'进程{i}')
        p1.start()
        lst.append(p1)
    for i in lst:
        i.join()
    print('父进程结束')
#Pool进程池
进程池对象=Pool(N)
-----------------------------------------
from multiprocessing import Pool
import os,time
def task(name):
    print(f'子进程PID:{os.getpid()},执行的任务:{name}')
    time.sleep(1)
if __name__ == '__main__':
    start=time.time()
    print('父进程开始执行')
    p=Pool(3)
    for i in range(10):
        p.apply_async(func=task,args=(i,))#非阻塞
        p.apply(func=task,args=(i,))#阻塞
    p.close()
    p.join()
    print('子进程执行完毕,父进程结束')
    print(time.time()-start)
#使用队列实现进程之间的通信
from multiprocessing import Queue,Process
import time
a=100
def write_msg(q):
    global a
    if not q.full():
        for i in range(6):
            a-=10
            q.put(a)
            print('a入队的值:',a)
def read_msg(q):
    time.sleep(1)
    while not q.empty():
        print('a出队的值:',q.get(a))
if __name__ == '__main__':
    q=Queue()
    p1=Process(target=write_msg,args=(q,))
    p2=Process(target=read_msg,args=(q,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    print('end')

创建线程的方式

#函数方式创建线程
import threading
from threading import Thread
import time
def test():
    for i in range(3):
        time.sleep(1)
        print(f'线程:{threading.current_thread().name}正在执行{i}')
if __name__ == '__main__':
    start=time.time()
    lst=[Thread(target=test)for i in range(2)]
    for i in lst:
        i.start()
    for i in lst:
        i.join()
    print(f'{time.time()-start}')
#继承式创建线程
import threading
from threading import Thread
import time
class SubThread(Thread):
    def run(self):
        for i in range(3):
            time.sleep(1)
            print(f'线程:{threading.current_thread().name}正在执行{i}')
if __name__ == '__main__':
    start = time.time()
    lst=[SubThread() for i in range(2)]
    for i in lst:
        i.start()
    for i in lst:
        i.join()
    print(f'{time.time()-start}')

你可能感兴趣的:(yy的学习之路,python)