PYTHON1.day16
day15回顾
生成器
能够动态提供数据的对象(现用现生成)
两种生成器:
生成器函数
含有yield语句的函数为生成器函数,此函数调用将返回生成器
生成器是可迭代对象
def myyield():
yield 1
yield 3
next(it) 函数将会让生成器函数执行,
生成表达式
(表达式 for 变量列表 in 可迭代对象 if 真值表达式)
字节串和字节数组
字节串 bytes (不可变)
创建:
b'' , b"", b'''''', b"""""", b'ABCD', b'\xA1'
bytes(), bytes(100), bytes(range(256)),
bytes('ABC中文', 'utf-8')
字节数组 bytearray (可变)
bytearray(), bytearray(100),
bytearray(range(256)), bytearray('ABC中文', 'utf-8')
运算:
+ += * *=
< <= > >= == !=
in / not in
索引和切片(注: 字节数组支持索引和切片赋值操作)
内建函数:
len(x), max(x), min(x), sum(x), any(x), all(x)
字节数组的方法:
B.clear()
B.append(n)
B.remove(value)
B.reverse()
B.decode()
B.find()
文件的读取操作
长期存储数据
文件的操作:
打开文件
读/写文件
关闭文件
打开函数:
f = open(文件路径名, mode='rt') 返回文件流对象
# 绝对路径或相对路径字符串
关闭方法:
f.close()
文本文件读方法:
f.read(字符数或字节数=-1)
f.readline() 读取一行,以换行符'\n'作为结束符
f.readlines() 读取多行,以换行符'\n'分隔,形成字符串
列表返回
文本文件的写操作
open(文件路径名, mode='rt')
mode 模式字符串的含义
r 读read
t 文本text
w 写write
x 创建新文件,如果文件存在则报错
a 追加append
详见文档:
python_base_docs_html/文件.html
写方法:
f.write()
f.writelines()
示例见:
file_write.py
file_write_x.py
file_write_a.py
1 # file_write.py 2 3 4 # 此示例示意写文件的基本操作 5 try: 6 # 1. 打开文件 7 f = open("mynote.txt", 'w') # 创建新文件 8 # 2. 写文件 9 f.write("ABCD\n") 10 f.write("你好!") 11 # f.write({1:"一"}) # 出错 12 f.writelines(["abcd", '1234']) 13 # 3. 关闭文件 14 f.close() 15 except OSError: 16 print("打开文件失败!") 17 18 19 20
1 2 3 # 此示例示意写文件的基本操作 4 try: 5 # 1. 打开文件 6 f = open("mynote.txt", 'x') # 创建新文件 7 # 2. 写文件 8 f.write("ABCD\n") 9 f.write("你好!") 10 # f.write({1:"一"}) # 出错 11 f.writelines(["abcd", '1234']) 12 # 3. 关闭文件 13 f.close() 14 except OSError: 15 print("打开文件失败!") 16 17 18 19
1 2 3 # 此示例示意写文件的基本操作 4 try: 5 # 1. 打开文件 6 f = open("mynote.txt", 'a') # 创建新文件 7 # 2. 写文件 8 f.write("ABCD\n") 9 f.write("你好!") 10 # f.write({1:"一"}) # 出错 11 f.writelines(["abcd", '1234\n']) 12 # 3. 关闭文件 13 f.close() 14 except OSError: 15 print("打开文件失败!") 16 17 18 19
文本文件操作
模式字符:
't' (默认)
说明:
1. 对文本文件的读写,需要用字符串(str) 进行读取和写入操作
2. 默认文件中存储的都为字符数据,在读写中会自动进行编解码
转换操作
3. 以行为单位分隔,在python内部统一用'\n' 作为换行符进行
分隔
各操作系统的换行符:
Linux换行符: '\n'
Windows换行符: '\r\n'
旧的Macintosh换行符: '\r'
新的 Mac OS X 换行符: '\n'
文本文件的迭代读取
文件流对象是可迭代对象,迭代过程中将以换行符'\n' 作为分隔符
依次获取
示例:
f = open('./mynote.txt')
for line in f:
print(line)
练习:
写一个函数,要求把一个字典组成的列表(学生信息列表),写入
文件si.txt中
要求:
内容是每个学生的信息写在一行内,每个信息之间用逗号分隔开
如:
def save_to_file(L):
....
L = [dict(name='xiaozhang', age=20, score=100),
dict(name='xiaoli', age=18, score=98)
]
save_to_file(L)
文件si.txt的内容是:
xiaozhang,20,100
xiaoli,18,98
1 # 练习: 2 # 写一个函数,要求把一个字典组成的列表(学生信息列表),写入 3 # 文件si.txt中 4 # 要求: 5 # 内容是每个学生的信息写在一行内,每个信息之间用逗号分隔开 6 # 如: 7 # def save_to_file(L): 8 # .... 9 10 # L = [dict(name='xiaozhang', age=20, score=100), 11 # dict(name='xiaoli', age=18, score=98) 12 # ] 13 # save_to_file(L) 14 # 文件si.txt的内容是: 15 # xiaozhang,20,100 16 # xiaoli,18,98 17 18 def save_to_file(L): 19 try: 20 f = open("si.txt", 'w') 21 # 循环写入每个学生的信息 22 for d in L: 23 # 每次写入一个学生的信息 24 f.write(d['name']) # 姓名 25 f.write(',') 26 f.write(str(d['age'])) # 年龄 27 f.write(',') 28 f.write(str(d['score'])) # 成绩 29 f.write('\n') # 换行 30 f.close() 31 print("保存成功") 32 except OSError: 33 print("保存失败!") 34 35 L = [dict(name='xiaozhang', age=20, score=100), 36 dict(name='xiaoli', age=18, score=98) 37 ] 38 save_to_file(L) 39 40 41
标准输入输出文件
sys.stdin 标准输入文件(ctrl + d 输入文件结束符)
sys.stdout 标准输出文件
sys.stderr 标准错误输出文件
模块名: sys
注: 标准文件不需要打开和关闭就可以使用
示例见:
stdout.py
1 # stdout.py 2 3 4 # 此示例示意标准输出文件 的用法 5 import sys 6 sys.stdout.write("hello world\n") 7 8 # sys.stdout.close() # 关闭文件 后,print() 将不再可用 9 10 print("hello world!!!") 11 12 f = open('myprint.txt', 'w') 13 print(1, 2, 3, 4, file=f) # 写入内容到文件 myprint.txt中 14 print("hello world!!!!!!!!!", file=f) 15 16
思考:
print() 函数是如何实现的?
能否自己实现一个myprint函数与内建功能相同
如:
print(*args, sep=' ', end='\n', file=sys.stdout,
flush=False)
1 import sys 2 sys.stderr.write("我的出现是个错误!!!!")
1 2 3 import sys 4 5 # s = input("请输入") # 内部就是调用sys.stdin 6 print("请输入内容:") 7 s = sys.stdin.readline() 8 print(s) 9 print(len(s)) # 算'\n'在内 10 11 s = sys.stdin.read() # ctrl + d 结束 12 print(s)
二进制文件操作
二进制文件操作模式字符:
'b'
说明:
1. 默认文件中存储的都是以字节(byte)为单位的数据,通常有人为规
定的格式
2. 对二进制文件的读写操作需要用字节串(bytes) 进行操作
什么是二进制文件
文件中以字节(byte)为单位存储和读写操作,不以字节串为单位
进行读写的文件操作方式
读方法:
F.read()
对于文本文件,F.read()返回类型为字符串(str)
对于二进制文件,F.read() 返回类型为字节串(bytes)
写方法:
F.write(x)
二进制模式时,x必须是字节串(bytes)
文件模式时,x必须是字符串(str)
示例见:
binary_file_write.py
binary_file_read.py
1 # binary_file_write.py 2 3 # 此示例示意写入256个字节到一个文件中 4 # 第一个字节为值为0, 第二个字节的值为1,....以此类推 5 try: 6 f = open('myfile.bin', 'wb') # 'wb'为二进制写操作 7 b = bytes(range(256)) # 创建一个256个字节的字节串 8 print(b) 9 r = f.write(b) # 写入256个字节到文件中 10 print("成功写入", r, '个字节') # 注f.write()返回值为写 11 # 入的字节数 12 f.close() 13 except OSError: 14 print("文件打开失败!")
1 # binary_file_read.py 2 3 4 # 此示例示意用二进制模式操作文件,实现读取文件myfile.bin数据 5 # 中的前10个字节 6 7 fr = open('myfile.bin', 'rb') 8 b = fr.read(10) # 此方法将返回字节串 9 print('b=', b) 10 fr.close() 11 12
F.tell() 方法
作用:
返回当前文件的读写位置(从文件头以字节为单位的整数)
见:
tell.py
F.seek方法
作用:
设置文件的读写位置
格式:
F.seek(偏移量, whence=相对位置)
偏移量
大于0的数代表向文件末尾方向移动
小于0代表向文件头方向移动
相对位置
0 代表从文件头开始偏移
1 代表从当前读写位置开始偏移
2 代表从文件尾开始偏移
示例见:
seek.py
1 # seek.py 2 3 # 此示例示意用seek方法来改变文件流的读写位置 4 5 f = open("char20.txt", 'rb') 6 print("当前文件的读写位置是", f.tell()) # 0 7 b = f.read(3) # b=b'ABC', 读写位置向后移动3个字节 8 print("读过三字节后的读写位置是:", f.tell()) 9 10 # 此处读取第5~9这五个字节 11 # 1. 从文件头开始偏移 12 # f.seek(5, 0) 13 # 2. 相对当前位置开始偏移 14 # f.seek(2, 1) 15 # 3. 相对文件尾向前开始偏移 16 f.seek(-15, 2) 17 18 19 print("移动后的文件读写位置是: ", f.tell()) # 5 20 b = f.read(5) 21 print('b=', b) 22 f.close() 23 24
F.flush方法
作用:
清空缓冲区
格式:
F.flush()
示例见:
flush.py
1 # flush.py 2 3 4 # 此示例示意文件缓冲的作用及清倒(清除)方法 5 6 fw = open("myflush.txt", 'w') 7 8 fw.write("hello") # 此处执行的write操作没有真正写在磁盘上 9 10 fw.flush() # 清空缓冲区 11 while True: # 进入死循环 12 pass 13 14 fw.close() 15
1 # flush.py 2 3 4 # 此示例示意文件缓冲的作用及清倒(清除)方法 5 6 fw = open("myflush.txt", 'w') 7 8 fw.write("hello") # 此处执行的write操作没有真正写在磁盘上 9 10 import time 11 while True: # 进入死循环 12 time.sleep(0.1) 13 print(time.time()) 14 fw.write('A'*1000+'\n') 15 16 fw.close() 17
1 # flush.py 2 3 4 # 此示例示意文件缓冲的作用及清倒(清除)方法 5 6 # print("hello", end=' ', flush=True) 7 print("hello", end=' ') 8 import sys 9 sys.stdout.flush() # 请空缓冲区 10 11 while True: 12 pass 13 14
文件操作小结:
二种打开模式:
文本文件方式(以字符串为单位进行操作,自动编码解码)
't'
二进制文件方式(字节串为单位进行操作, 不进行编解码)
'b'
二种IO操作(input读, output写)
读操作: 'r'
F.read()
F.readline()
F.readlines()
写操作: 'w', 'x', 'a'
F.write(x)
F.writelines(x)
文件的关闭:
F.close()
文件读写位置的定位操作:
F.tell()
F.seek()
清空缓冲区操作:
F.flush()
汉字编码
国标系列:
GB18030(收录27533个汉字, 二字节或四字节编码)
GBK(收录21003个汉字,二字节编码)
GB2312(收录6763个汉字+682个全角符号, 二字节编码)
(Windows常用)
国际标准:
Unicode32(32位表示的文字编码)
Unicode16(16位表示的文字编码)
(Linux / Mac OS X / IOS / Android常用)
UTF-8
UTF-8(8-bit Unicode Transformation Format)
0x0000 ~ 0x007F 一字节编码
0x0080 ~ 0x07FF 二字节编码
0x0800 ~ 0xFFFF 三字节编码(中文落在此区)
问题:
十个汉字点多少个字节?
python 编码转换字符串:
'gb2312'
'gbk'
'gb18030'
'utf-8'
'ascii'
用于s.encode(x) 和 b.decode(x)中
如:
s = '十个汉字点多少个字节'
print(s.encode('gbk'))
print(s.encode('utf-8'))
编码注释:
在源文件的第一行或第二行写入如下内容为编码注释
# -*- coding:gbk -*-
或
# -*- coding:utf-8 -*-
作用:
指示python3解释执行器,当前文件的编码方式是什么
示例见:
hello_gbk.py
# -*- coding:gbk -*-
print("hello中文")
练习:
修改学生信息管理程序,
再加入一个保存的功能:
| 10) 保存信息到文件(si.txt) |
实现保存当前的所有数据
1 # file : main.py 2 3 from menu import show_menu 4 from student_info import * 5 6 def main(): 7 infos = [] # 此列表用于保存学生数据 8 while True: 9 show_menu() 10 s = input("请选择: ") 11 if s == '1': 12 infos += input_student() 13 elif s == '2': 14 output_student(infos) 15 elif s == '3': 16 delete_student(infos) 17 elif s == '4': 18 modify_student_score(infos) 19 elif s == '5': 20 output_by_score_desc(infos) 21 elif s == '6': 22 output_by_score_asc(infos) 23 elif s == '7': 24 output_by_age_desc(infos) 25 elif s == '8': 26 output_by_age_asc(infos) 27 elif s == '9': 28 infos = read_from_file() 29 elif s == '10': 30 save_to_file(infos) # 保存 31 elif s == 'q': 32 break 33 34 main() 35
1 # file : menu.py 2 3 4 def show_menu(): 5 '''显示菜单''' 6 print("+---------------------------------+") 7 print("| 1) 添加学生信息 |") 8 print("| 2) 显示学生信息 |") 9 print("| 3) 删除学生信息 |") 10 print("| 4) 修改学生成绩 |") 11 print("| 5) 按学生成绩高-低显示学生信息 |") 12 print("| 6) 按学生成绩低-高显示学生信息 |") 13 print("| 7) 按学生年龄高-低显示学生信息 |") 14 print("| 8) 按学生年龄低-高显示学生信息 |") 15 print("| 9) 从文件中读取学生数据(si.txt) |") 16 print("| 10) 保存信息到文件(si.txt) |") 17 print("| q) 退出 |") 18 print("+---------------------------------+") 19 20
1 # file: student.py 2 3 def input_student(): 4 L = [] # 创建一个列表,准备存放学生数据的字典 5 while True: 6 n = input("请输入姓名: ") 7 if not n: # 如果用户输入空字符串就结束输入 8 break 9 try: 10 a = int(input("请输入年龄: ")) 11 s = int(input("请输入成绩: ")) 12 except ValueError: 13 print("您的输入有错,请重新输入!!!") 14 continue 15 d = {} # 一定要每次都创建一个新的字典 16 d['name'] = n 17 d['age'] = a 18 d['score'] = s 19 L.append(d) # 把d加入列表中L 20 return L 21 22 def output_student(L): 23 print("+---------------+----------+----------+") 24 print("| 姓名 | 年龄 | 成绩 |") 25 print("+---------------+----------+----------+") 26 for d in L: 27 name = d['name'] 28 age = str(d['age']) # 转为字符串 29 score = str(d['score']) # 转为字符串 30 print("|%s|%s|%s|" % (name.center(15), 31 age.center(10), 32 score.center(10))) 33 print("+---------------+----------+----------+") 34 35 def delete_student(L): 36 name = input("请输入要删除学生的姓名: ") 37 i = 0 # i 代表列表的索引 38 while i < len(L): 39 d = L[i] # d绑定字典 40 if d['name'] == name: 41 del L[i] 42 print("删除", name, "成功!") 43 break 44 i += 1 45 else: 46 print("删除失败!") 47 48 def modify_student_score(L): 49 pass 50 51 52 def output_by_score_desc(L): 53 def get_score(d): 54 return d['score'] 55 L2 = sorted(L, key=get_score, reverse=True) 56 output_student(L2) 57 58 def output_by_score_asc(L): 59 L2 = sorted(L, key=lambda d:d['score']) 60 output_student(L2) 61 62 def output_by_age_desc(L): 63 L2 = sorted(L, key=lambda d:d['age'], reverse=True) 64 output_student(L2) 65 66 def output_by_age_asc(L): 67 L2 = sorted(L, key=lambda d:d['age']) 68 output_student(L2) 69 70 71 def read_from_file(): 72 L = [] # 创建一个准备存放字典的列表 73 try: 74 # 1. 打开文件 75 # f = open("./si.txt") 76 # f = open("si.txt") 77 f = open("/home/tarena/aid1812/pbase/day16/student_project/si.txt") 78 # 2. 读取信息 79 try: 80 while True: 81 line = f.readline() # line='xiaozhang,20,100\n' 82 if not line: # 到达文件尾 83 break 84 s = line.strip() # 去掉左右两端的空白字符'xiaozhang,20,100' 85 lst = s.split(',') # ['xiaozhang', '20', '100'] 86 n = lst[0] 87 a = int(lst[1]) 88 scr = int(lst[2]) 89 d = dict(name=n, age=a, score=scr) 90 L.append(d) 91 finally: 92 # 3. 关闭文件 93 f.close() 94 print("读取数据成功") 95 except OSError: 96 print("读取数据失败") 97 except ValueError: 98 print("数据类型错误!") 99 return L 100 101 def save_to_file(L): 102 try: 103 f = open("si.txt", 'w') 104 # 循环写入每个学生的信息 105 for d in L: 106 # 每次写入一个学生的信息 107 f.write(d['name']) # 姓名 108 f.write(',') 109 f.write(str(d['age'])) # 年龄 110 f.write(',') 111 f.write(str(d['score'])) # 成绩 112 f.write('\n') # 换行 113 f.close() 114 print("保存成功") 115 except OSError: 116 print("保存失败!") 117
练习:
写程序,实现复制文件的功能:
如:
请输入源文件: /home/tarena/day16.txt
请输入目标文件: /home/tarena/abc.txt
输出:
复制文件成功
要求:
1. 要考虑文件关闭的问题
2. 要考虑大文件的问题
3. 要能复制二进制文件
答案参见:
mycopy.py
1 # 练习: 2 # 1. 写程序,实现文件的复制,(注:只复制文件,不复制文件夹) 3 # 要求: 4 # 1) 要考虑文件关闭的问题 5 # 2) 要考虑超大文件无法一下加载到内存的问题 6 # 3) 要能复制二进制文件(非文本文件) 7 8 def copy(src_file, dst_file): 9 ''' src_file : 源文件名 10 dst_file : 目标文件名 11 返回值: True成功, False 失败 12 ''' 13 try: 14 fr = open(src_file, 'rb') 15 try: 16 fw = open(dst_file, 'wb') 17 try: 18 while True: 19 b = fr.read(4096) 20 if not b: 21 break 22 fw.write(b) 23 finally: 24 fw.close() 25 finally: 26 fr.close() 27 except OSError: 28 return False 29 return True 30 31 src = input("请输入源文件名: ") 32 dst = input("请输入目标文件名: ") 33 if copy(src, dst): 34 print("复制文件成功!") 35 else: 36 print("复制文件失败!")