文件操作

昨日回顾

1. 基本数据类型补充
        join() 把传递进去的参数进行迭代然后和前面的字符串进行拼接, 返回字符串
        split() 把字符串切割成列表

        关于删除:
            列表在循环的时候不能直接删除. 因为索引会发生改变. 把要删除的内容保存在新列表中,
            然后循环这个新列表. 删除老列表

            字典在循环的时候也不能直接删除. 如果删除会报错

        fromkeys() 创建字典
        坑1: 返回新字典, 对原来的字典没有影响
        坑2: 如果给的value是可变的数据类型. 多个key共享同一个value.

    2. 深浅拷贝
        1. = 没有创建新的对象.
        2. lst.copy()  lst[:] 浅拷贝, 拷贝第一层内容
        3. import  copy
            copy.deepcopy()  深拷贝.
            把列表内的所有内容进行拷贝和复制

今日内容

1. 文件操作
        open 打开
        f = open(文件路径, mode="模式", encoding="编码格式") 最最底层操作的就是bytes
        打开一个文件的时候获取到的是一个文件句柄.##f是文件句柄,相当于吸管/锅把(只是个媒介而已),而不是文件本身

        绝对路径
            从磁盘根目录开始寻找
        相对路径
            相对于当前程序所在的文件夹
            ../ 上一层文件
            文件夹/ 进入xxx文件夹

    2. mode:
    注意:读的好习惯是f.close()
      写的好习惯是f.flush() f.close()
r: 读取,只读. 读取文件的相关操作
1. read() 默认: 读取文件内容(全部) read(n) 读取n个字符(##不管是中文还是英文,还是读出来的字节,都当成是一个字符) 2. readline() 读取一行 3. readlines() 读取全部. 返回列表 (最重要)4. for line in f: 每次读取一行内容 w: 写入. 只写 创建文件 会清空文件(##覆盖写) a: 也可以创建文件 追加写 r+: 对于文件而言. 应该有的操作就两个:读, 写 读写操作 w+: 写读操作 a+: 追加写读 所有带b的表示直接操作的是bytes, 当处理非文本文件的时候. rb wb ab: 断点续传 r+b w+b a+b 3. 文件操作中关于文件句柄的相关操作 seek() 移动光标 f.seek(0) 移动到开头(最多) ##等价于seek(0,0),从开头位置(第二个参数0)偏移0个字节(第一个参数0) f.seek(0, 2) 移动到末尾 ##从末尾位置偏移0个字节 seek:两个参数 1. 表示偏移量 2. 从xxx开始偏移, 默认0开头 1当前位置 2末尾 tell 返回光标所在的位置
    

      truncate(n), 如果给出了n. 则从开头开头进⾏截断, 如果不给n, 则从当前位置截断. 后⾯的内容将会被删除

        有n,留下的是从文件的开头到n个字节
        没有n,留下的是从文件的开头到当前位置所在的字节
4.实际操作(重点)
  文件复制
  文件修改
  水果统计

一.初识文件操作

# r: read 只读
# f是文件句柄,相当于吸管/锅把,而不是文件本身
# 这里的 encoding="utf-8" 包含一个decode的过程,具体的不太清晰???
f = open("alex和wusir的故事", mode="r", encoding="utf-8")
# 读取内容
content = f.read()  # 全部都读取出来
print(content)

# 坑:
c2 = f.read() # 读取不到内容. 因为上面已经读取完毕. 光标在末尾
print("c2", c2)

# 良好的习惯-->read的
f.close() # 关闭连接
文件操作
# 文件路径:
#   1. 相对路径: 相对于当前程序所在的文件夹, 如果在文件夹内,直接写名字
#       如果不在这个文件夹内,可能需要出文件夹或者进文件夹
#           出文件夹  ../ (出文件夹不需要标注出出来哪个文件夹,直接../就是走出了该文件当前所在的文件夹)
#           进文件夹  要进的文件夹的名字/
#   2. 绝对路径: 从磁盘根目录寻找路径 (有问题:代码传输之后,如果文件更改了路径就要相应的更改代码里面的路径)
#           只有在记录日志的时候可以用到绝对路径(因为日志信息一般只会读,不会去更改)
# 日志: 程序运行过程中记录的信息.

# 'utf-8' codec can't decode byte 0xbd in position 0: invalid start byte
f = open("E:西游记金角大王吧.txt", mode="r", encoding="gbk")  # 直接在win电脑上创建的文本文件是使用的'gbk'编码的
print(f.read())
f.close()
文件路径

使用python来读写文件是非常简单的操作.我们使用open0函数来打开一个文件,获取到文件句柄.然后通过文件句柄就可以进行各种各样的操作了.根据打开方式的不同能够执行的操作也会有相应的差异.
打开文件的方式:r, w, a, r+, W+, a+, rb, wb, ab, r+b, w+b, a+b默认使用的是r(只读)模式

绝对路径和相对路径:

1.绝对路径:从磁盘根目录开始一直到文件名.
2.相对路径:同-个文件夹下的文件.相对于当前这个程序所在的文件夹而言.如果在同
一个文件夹中则相对路径就是这个文件名.如果在上- -层文件夹则要../

我们更推荐大家使用相对路径.因为在我们把程序拷贝给别人使用的时候.直接把项目拷贝走
就能运行.但是如果用绝对路径.那还需要拷贝外部的文件.

二.mode

只读(r, rb)

f = open("小护士模特主妇萝莉.txt", mode="r", encoding="utf-8")
print(f.read(5))  # 读取5个字符  ##不管是中文还是英文
print(type(f.read(5)))  # <class 'str'>
print(f.read(5))  # 继续读5个

print(f.readline().strip()) # 读取一行的内容,以换行符作为分割符, 用strip()可以去掉换行. 读取到的内容第一件事就是去掉空白
print(f.readline()) ## 打印的结果会两次换行(即行与行之间会间隔一个空行).因为readline()读取的内容中末尾是
会换行,而print方法的参数默认end = '
'末尾会有一个换行效果
# 去掉多余的换行的方法
print(f.readline().strip()) #去掉readline()里面的'
'
print(f.readline(), end='') #去掉print()里面的'
'

# 良好的习惯-->read的
f.close()

print("周润发", end="胡辣汤") # print里面的end参数可以随意自定义修改
print("周星驰")

print(f.readlines())  #  一次性把文件中的内容读取到列表中.##每个元素是文件一行的内容和
,最后一行可能没有换行符,就看当初写的时候有没有写进去了.(换行符在文件中是直接行使作用的,是看不到以字符'
'的样子显示出来的,文件会自动将它的效果显示出来-->对每一行的文件内容进行换行;而将文件中的内容读取出来的时候,相当于将文件还原成当初的代码)
 #代码中的'
'<--->文件中的换行效果   是对应的   代码是给机器看的,文件是给我们看的.



print("你叫什么名字?
 我叫李嘉诚. 可能") #  换行
print("你叫什么名字?\n 我叫李嘉诚. 可能") #  显示 
(用来转义)
print("你叫什么名字?\\n 我叫李嘉诚. 可能") #  显示 \n


# 文件句柄是一个可迭代对象 ##迭代出来的是文件每一行的内容
# 优点: 相对来说节省内存, 操作相对简单
for line in f:  # 从文件中读取到每一行给前面的line
    print(line.strip())
f.close()



import pickle
print(pickle.dump('我爱我家', open('aaa','wb')))  # 使用pickle序列化之后得到字节码再写入文件

f = open("aaa", mode="rb")
print(f.read(5))  # b'x80x03Xx0cx00' 读取5个字符  ##不管是中文还是英文,还是读出来的字节,都当成是一个字符
print(len(f.read(5)))  # 5
print(type(f.read(5)))  # <class 'bytes'>

"""
f.read(5)#读取的是字符,但是所谓的字符是 不管是中文还是英文,还是读出来的字节,都当成是一个字符
"""
mode_r
f = open("护士少妇嫩模. txt" , mode="r", encoding= "utf-8")
content = f. read()
print(content)
f.close()

需要注意encoding表示编码集.根据文件的实际保存编码进行获取数据,对于我们而言.更多的是utf-8.

rb.读取出来的数据是bytes类型,在rb模式下.不能选择encoding字符集.

f = open("护士少妇嫩模. txt" , mode="rb" )
content = f . read()
print(content)
f.close()
结果:
b'xe6xafx85xe5x93xa5, xe5xa4xaaxe7x99xbd,
wuse
xe5x91xb5xe5x91xb5
xe6x97xa5xe5xa4xa9'

rb的作用:在读取非文本文件的时候.比如读取MP3.图像.视频等信息的时候就需要用到rb.因为这种数据是没办法直接显示出来的.在后面我们文件上传下载的时候还会用到.还有我们看的直播.实际上都是这种数据.



读取文件的方法:
1. read( 将文件中的内容全部读取出来.弊端:占内存.如果文件过大容易导致内存崩溃

f = open("../def/哇擦. txt", mode="r", encoding="utf-8")
content = f. read()
print(content)
结果:
友谊地久天长,
爱一点,
可惜我是水瓶座
一生中最爱

2. read(n) 读取n个字符.需要注意的是.如果再次读取.那么会在当前位置继续去读而不
是从头读,如果使用的是b模式.则读取出来的是n个字节

f = open(". ./def/哇擦. txt", mode=" r” encoding= "utf-8")
content = f. read(3)
print(content)
#结果:
友谊地

f = open("../def/哇擦.txt", mode="rb") content = f.read(3)
print(content)
#结果: b'xe5x8fx8b'

f = open("../def/哇擦.txt", mode="r", encoding="utf-8") content = f.read(3)
content2 = f.read(3)
print(content)
print(content2)
#结果: 
友谊地 
久天⻓长

3. readline() 一次读取一⾏数据, 注意: readline()结尾, 注意每次读取出来的数据都会有一 个 所以呢. 需要我们使用strip()方法来去掉 或者空格

 f = open("../def/哇擦.txt", mode="r", encoding="utf-8") content = f.readline()
content2 = f.readline()
content3 = f.readline()
content4 = f.readline()
content5 = f.readline()
content6 = f.readline()
print(content)
print(content2)
print(content3)
print(content4)
print(content5)
print(content6)
结果: 友谊地久天⻓长, 爱⼀一点, 可惜我是⽔水瓶座 ⼀一⽣生中最爱

4. readlines()将每一行形成一个元素,放到一个列表中.将所有的内容都读取出来.所以也是容易出现内存崩溃的问题.不推荐使⽤

f = open("../def/哇擦.txt", mode="r", encoding="utf-8") lst = f.readlines()
print(lst)
for line in lst:
    print(line.strip())

5. 循环读取.这种方式是组好的.每次读取一⾏内容.不会产生内存溢出的问题.

f = open("../def/哇擦.txt", mode="r", encoding="utf-8") 

for line in f: print(line.strip())

注意: 读取完的文件句柄一定要关闭  f.close()

只写(w, wb)

# 每次用w模式打开文件, 都会清空这个文件(坑)
f = open('胡辣汤', mode="w", encoding="utf-8") # 可以帮我们创建文件

f.write('河南特色
')
f.write("东北特色
")
f.write('陕西特色
')

# 好习惯 --> write的
f.flush()  # 刷新管道(##管道:文件句柄f), 把数据写入文件
f.close()

print('我爱我家'.encode('utf-8'))
mode_w

写的时候注意. 如果没有文件, 则会创建文件,;如果文件存在.,则将文件中原来的内容删除, 再写入新内容

f = open("⼩小娃娃", mode="w", encoding="utf-8") 
f.write("⾦金金⽑毛狮王")
f.flush() # 刷新. 养成好习惯
f.close()

尝试读一读

f = open("⼩小娃娃", mode="w", encoding="utf-8") 
f.write("⾦金金⽑毛狮王")
#f.read() # 报错not readable 模式是w. 不可以执行读操作 
f.flush()
f.close()

wb模式下. 可以不指定打开⽂文件的编码. 但是在写⽂文件的时候必须将字符串串转化成utf-8的 bytes数据

f = open("⼩小娃娃", mode="wb") 
f.write("⾦金金⽑毛狮王".encode("utf-8")) 
f.flush() f.close()

追加(a, ab)

f = open("葫芦小金刚", mode="a", encoding="utf-8") # a, append 追加, 在文件的末尾写入内容
f.write("你叫什么名字啊?")
# f.read() # 报错not readable  因为追加是写的模式,不能读
f.flush()
f.close()
mode_a

在追加模式下. 我们写入的内容会追加在文件的结尾.

f = open("⼩小娃娃", mode="a", encoding="utf-8") 
f.write("麻花藤的最爱")
f.flush()
f.close()

mode_+

f = open("葫芦小金刚", mode="r+", encoding="utf-8")
content = f.read(2)  # 顺序必须先读, 后写  ##上来就先写也不会报错,但是开始的光标是在文件的开头,你写进去几个字符,原有的文件就会被相应的覆盖掉几个字符
# r+特有的深坑:不论读取内容的多少. 只要你读了. 写就是在末尾
f.write('五娃')
print(content)


# 一上来会清空文件. 没人用
f = open("葫芦小金刚", mode="w+", encoding="utf-8")
f.write("又能吐火的, 有能吐水的.")
print(f.tell())  # 33 返回光标的位置.写完光标就在末尾了,不移动光标就读是读不到内容的
# 移动光标
f.seek(0) # 移动到开头
s = f.read()
print("=========>", s)


# 追加写读, 光标在末尾. 所有的写都是在末尾
f = open("葫芦小金刚", mode="a+", encoding="utf-8")
f.write("机器葫芦娃召唤神龙, 高喊.我代表月亮消灭你!")
f.seek(0)
s = f.read()
print("=========>", s)
mode_+

 r+读写

对于读写模式. 必须是先读. 因为默认光标是在开头的. 准备读取的. 当读完了之后再进⾏写入. 我们以后使⽤频率最高的模式就是r+

正确操作是:(先读后写)

f = open("⼩小娃娃", mode="r+", encoding="utf-8") 
content = f.read()
f.write("麻花藤的最爱")
print(content)
f.flush()
f.close()

#结果:
正常的读取之后, 写在结尾

错误操作:(先写后读)

f = open("⼩小娃娃", mode="r+", encoding="utf-8") 
f.write("哈哈")
content = f.read()
print(content)
f.flush()
f.close()
#结果: 
将开头的内容改写成了"哈哈", 然后读取的内容是后面的内容.(写入的内容把原本所在的位置覆盖了)

所以记住: r+模式下. 必须是先读取. 然后再写入

w+写读

先将所有的内容清空. 然后写入. 最后读取. 但是读取的内容是空的, 不常⽤

f = open("⼩小娃娃", mode="w+", encoding="utf-8") f.write("哈哈")
content = f.read()
print(content)
f.flush()
f.close()

有人会说. 先读不就好了么? 错. w+ 模式下, 一开始读取不到数据. 然后写的时候再将原来的内容清空. 所以, 很少用.

a+写读[追加写读)

a+模式下, 不论先读还是后读. 都是读取不到数据的.(因为打开文件光标就在末尾,写完之后还是在末尾,必须要移动光标才能读取到数据)

f = open("⼩小娃娃", mode="a+", encoding="utf-8") f.write("⻢马化腾")
content = f.read()
print(content)
f.flush()
f.close()

还有一些其他的带b的操作. 就不多赘述了. 就是把字符换成字节. 仅此⽽已

其他操作方法

f = open("胡辣汤", mode="r+", encoding="utf-8")
f.seek(0,2) # 移动到末尾
content = f.read(5) #以字符为单位
print(content)
f.seek(0) # 移动到开头
print(f.read()) # 以字节为单位
print(f.tell())  # 以字节为单位

f.seek(3)
print(f.read())
View Code

1. seek(n)

光标移动到n位置, 注意, 移动的单位是byte. 所以如果是UTF-8的中文部分要是3的倍数.通常我们使用seek都是移动到开头或者结尾.

移动到开头: seek(0)
移动到结尾: seek(0,2) seek的第二个参数表示的是从哪个位置进⾏偏移, 默认是0, 表示开头, 1表示当前位置, 2表示结尾

seek(0,0)文件开头
seek(0,1)文件当前位置
seek(0,2)文件末尾

f = open("⼩小娃娃", mode="r+", encoding="utf-8") 
f.seek(0) # 光标移动到开头
content = f.read() # 读取内容, 此时光标移动到结尾 
print(content)
f.seek(0) # 再次将光标移动到开头 
f.seek(0, 2) # 将光标移动到结尾
content2 = f.read() # 读取内容. 什什么都没有 
print(content2)
f.seek(0) # 移动到开头 f.write("张国荣") # 写⼊入信息. 此时光标在9 中⽂文3 * 3个 = 9

f.flush() f.close()

2. tell()

使用tell()可以帮我们获取到当前光标在什么位置

f = open("⼩小娃娃", mode="r+", encoding="utf-8") 
f.seek(0) # 光标移动到开头
content = f.read() # 读取内容, 此时光标移动到结尾
print(content)
f.seek(0) # 再次将光标移动到开头 
f.seek(0, 2) # 将光标移动到结尾
content2 = f.read() # 读取内容. 什什么都没有
print(content2)
f.seek(0) # 移动到开头 f.write("张国荣") # 写⼊入信息. 此时光标在9 中⽂文3 * 3个 = 9 print(f.tell()) # 光标位置9 f.flush() f.close()

3. truncate()截断文件

f = open("⼩小娃娃", mode="w", encoding="utf-8") 
f.write("哈哈") # 写⼊两个字符
f.seek(3) # 光标移动到3, 也就是两个字中间 
f.truncate() # 删掉光标后面的所有内容
f.close()
f = open("⼩小娃娃", mode="r+", encoding="utf-8") content = f.read(3) # 读取12个字符 f.seek(4) print(f.tell()) f.truncate() # print(content) f.flush() f.close()

深坑请注意: 在r+模式下. 如果读取了内容. 不论读取内容多少. 光标显示的是多少. 再写入或者操作文件的时候都是在结尾进⾏的操作.

所以如果想做截断操作. 记住了. 要先挪动光标. 挪动到你想要截断的位置. 然后再进⾏截断.

关于truncate(n), 如果给出了n. 则从开头开头进⾏截断, 如果不给n, 则从当前位置截断. 后⾯的内容将会被删除

有n,留下的是从文件的开头到n个字节
没有n,留下的是从文件的开头到当前位置所在的字节

栗子:

f = open("a1.txt", mode="r+", encoding="utf-8")
f.readline()  
print(f.truncate())# 没有截断的效果,原文件不变
f.seek(18)  # 涉及到byte才截断
print(f.truncate())# 截断到18


## 下面是我自己搜的
f=open('woo.txt','r+')
print(f.readline())
f.tell() # 9读取后位置
f.truncate() # 返回值34,整个文件
f.seek(9) # 定位到9  ## 涉及到byte才截断
f.truncate() # 返回值9,已截断,所以truncate如果不传参数,之前需要先调一次seek定位(只是在r+模式下)
# 因此猜测python底层是这么写的
def _truncate(self): # 真实的truncate
    # 函数内容省略
    pass
def truncate(self, size=None): # 你用的truncate
    if size: # 不传size需要手动调用一次seek
        self.seek(size)
    self._truncate()

应用

文件复制_bytes

f1 = open("c:/huyifei.jpg", mode="rb")
f2 = open("d:/huerfei.jpg", mode="wb")

for line in f1: # line是从f1中读取的内容
    f2.write(line)  # 把读取的内容原封不动的写出去

f1.close()
f2.flush()
f2.close()
# 文件复制操作流程
# 1.拿到文件1的句柄以读模式打开,拿到文件2的句柄以写的模式打开
# 2.遍历(对文件的遍历是拿到每行的文件内容)文件1写入文件2中

文件的修改以及另-种打开文件句柄的方式

# 需求: 对文件'夸一夸alex' 把好人换成sb
# 必须:(文件修改的操作步骤)
#   1. 先从文件中读取内容-->(遍历文件)
#   2. 把要修改的内容进行修改-->(replace替换,并赋值,拿到修改好的内容)
#   3. 把修改好的内容写入一个新文件
#   4. 删除掉原来的文件 --> os.remove(老文件名)
#   5. 把新文件重命名成原来的文件的名字

# 导入os模块  os表示操作系统
import os

# f = open("夸一夸alex", mode="r", encoding="utf-8")
# f2 = open("夸一夸alex_副本", mode="w", encoding="utf-8")

# with会自动的帮我们关闭文件的链接
with open("夸一夸alex", mode="r", encoding="utf-8") as f, 
     open("夸一夸alex_副本", mode="w", encoding="utf-8") as f2:

    for line in f:  # 1.遍历文件
        if "好人" in line:
            line = line.replace("好人", "sb")  # 2.replace替换,并赋值,拿到修改好的内容
        f2.write(line)  # 3. 把修改好的内容写入一个新文件(存在,写入修改后的;不存在,写入原来的)

# time.sleep(3) # 程序暂停3秒

# 4.删除原来文件
os.remove("夸一夸alex")

# 5.重命名副本为原来的文件名
os.rename("夸一夸alex_副本", "夸一夸alex")
View Code

文件修改: 只能将文件中的内容读取到内存中, 将信息修改完毕, 然后将源文件删除, 将新文件的名字改成老文件的名字.

 # 文件修改 
import os

with open("⼩小娃娃", mode="r", encoding="utf-8") as f1, open("⼩小娃娃_new", mode="w", encoding="UTF-8") as f2:
    content = f1.read()
    new_content = content.replace("冰糖葫芦", "⼤大⽩白梨梨") 
    f2.write(new_content)
os.remove("⼩小娃娃") # 删除源⽂文件 os.rename("⼩小娃娃_new", "⼩小娃娃") # 重命名新⽂文件

弊端: 一次将所有内容进行读取. 内存溢出.

解决⽅案: 一⾏一行的读取和操作

import os
with open("⼩小娃娃", mode="r", encoding="utf-8") as f1, open("⼩小娃娃_new", mode="w", encoding="UTF-8") as f2:
    for line in f1:
        new_line = line.replace("⼤大⽩白梨梨", "冰糖葫芦") 
        f2.write(new_line)
os.remove("⼩小娃娃") # 删除源⽂文件 os.rename("⼩小娃娃_new", "⼩小娃娃") # 重命名新⽂文件    

水果统计

文件  水果.txt 内容如下:

编号,名称,价格,数量
1,香蕉,1.85,50
2,苹果,2.6,67
3,榴莲,25,78
4,木瓜,3.5,89
# 文件的实际操作
# 需求:将文件'水果.txt' 转化成下面的列表中嵌套字典的样式,其中的key:编号,名称,价格,数量  均是文件第一行的的内容
# [{'编号': '1', '名称': '香蕉', '价格': '1.85', '数量': '50'},
#  {'编号': '2', '名称': '苹果', '价格': '2.6', '数量': '67'},
#  {'编号': '3', '名称': '榴莲', '价格': '25', '数量': '78'},
#  {'编号': '4', '名称': '木瓜', '价格': '3.5', '数量': '89'}]

# 方法一
##缺点:这个的key是自定义写死的
f = open("水果.txt", mode="r", encoding="utf-8")

lst = []
for line in f:  # 1,香蕉,1.85,50
    dic = {}  # 每行都是一个字典
    line = line.strip()  # 去掉空白  
 1,香蕉,1.85,50
    a, b, c, d = line.split(",") # [1, 香蕉, 1.85, 50]
    dic['id'] = a
    dic['name'] = b
    dic['price'] = c
    dic['totle'] = d
    lst.append(dic)

print(lst)




# 方法二
##缺点:这个每种水果的属性不便于修改(比如:增加个属性'总价',或者删除个属性'编号',都要相应的去修改原来的代码,主要是由于解构时候变量的数量给写死了)
f = open("水果.txt", mode="r", encoding="utf-8")
line = f.readline().strip() # 第一行内容,   编号,名称,价格,数量,哈哈
h,i,j,k = line.split(",")
lst = []
for line in f:  # 1,香蕉,1.85,50
    dic = {}  # 每行都是一个字典
    line = line.strip()  # 去掉空白  
 1,香蕉,1.85,50
    a, b, c, d = line.split(",") # [1, 香蕉, 1.85, 50]
    dic[h] = a
    dic[i] = b
    dic[j] = c
    dic[k] = d
    lst.append(dic)

print(lst)


# 方法三
##这个使用遍历,完美的解决了上面没办法动态修改属性数量的问题
f = open("水果.txt", mode="r", encoding="utf-8")
line1 = f.readline().strip() # 第一行内容,   编号,名称,价格,数量,哈哈
title = line1.split(",") # [编号,名称,价格,数量]
lst = []
# i = 0

for line in f:  # 1,香蕉,1.85,50
    dic = {}  # 每行都是一个字典 读到每一行都要初始化一个空字典
    line = line.strip()  # 去掉空白  
 1,香蕉,1.85,50
    data = line.split(",")  # [1, 香蕉, 1.85, 50]

    for i in range(len(title)):  # #遍历列表title和data都可以,因为它们的长度相同,索引相同
        dic[title[i]] = data[i]

    lst.append(dic)

print(lst)

今日作业

今日作业及默写

原文地址:https://www.cnblogs.com/lyfstorm/p/11155004.html