You are on page 1of 90

计算机程序设计基础 Python

清华大学计算机科学与技术系 乔 林
第四章 文本处理 Python
清华大学计算机科学与技术系 乔 林
4.1  字符串
4.2  字符串格式化
4.3  文 件
4.4   密码服务

第四章 文本处理 3
计算机程序设计基础( Python ) 4
4.1  字符串
4.2  字符串格式化
4.3  文 件
4.4   密码服务

第四章 文本处理 5
4.1  字符串 6
4.1.2  子字符串
4.1.3  字符串操作符
4.1.4  字符串函数
4.1.1  字符串类型 4.1.5  字符串方法
4.1.1  字符串类型
• 字符串类型 str :字符序列( sequence )
• 注意: Python 无字符类型
• 字符串编码: Unicode 编码
• 单个中文字符和英文字符均计数为一
• 字符串文字
• 转义字符序列
• 转义字符序列计数为一

7
字符串文字
• 字符串文字定界符:单引号,双引号与三引号
• 三引号单双均可,可跨行
• 相关白空间(空格、 Tab 键)为字符串内容
• 字符串文字合并
• 仅以白空间分隔的双字符串文字自动合并
• 示例: "Hello" "World" 合并为 "HelloWorld"

8
转义字符序列
• 转义字符序列( escape sequence ):以“ \” 起始的字
符串,具有特定意义
• 常用转义字符序列
• “\n” :换行
• “\\” :反斜杠自身
• “\b” :退格
• “\t” :水平制表符;“ \v” :垂直制表符
• “\"” :双引号字符;“ \'” :单引号 字符

9
补遗:文档字符串
• 格 式:三引号构造的多行字符串,可选
• 若存在,必须为函数、类或模块的首条表达式
• 编译时字符串文字赋值给相应函数、类或模块 __doc__ 属性,
作为其文档字符串( docstring );执行脚本代码时忽略
• 说 明
• 文档字符串首行:功能摘要行,必须简洁,以描述对象目的
• 其余行:第二行必须为空白行,以分隔文档字符串摘要与具体
描述
• 意 义:对象文档自动化
10
补遗:文档字符串
• 文档字符串示例
>>> def doc_string_sample():
... """Do nothing, but document it.
...
... No, really, it doesn't do anything.
... """
... pass
...
>>> print(doc_string_sample.__doc__)
Do nothing, but document it.

No, really, it doesn't do anything.

11
4.1.2  子字符串
• 字符索引下标:特定字符在字符串中的位置
• 正向递增:设字符串长度为 n ,字符串首字符编号为 0 ,其
后依次递增至 n–1
• 反向递减:设字符串长度为 n ,字符串尾字符编号为– 1 ,
其前依次递减至 – n
• 单一字符处理
• Python 无字符型,仅包括单一字符的子串依然为字符串
• 示例:若 i 表示字符串 s 中特定字符的索引下标,使用 s[ i
] 引用该字符(串)
12
字符串索引下标示例一
>>> s = "Python 程序设计 " # 注意引号的全角与半角问题
>>> print(s) # 字符串长度为十个字符
'Python 程序设计 '
>>> s[0] # 首字符
'P'
>>> s[9] # 尾字符
'计'
>>> s[-1] # 尾字符
'计'
>>> s[-10] # 首字符
'P'
>>>

13
字符串区间子串
• 不限串长的字符串区间访问方法
• 访问格式: [m : n]
• 目的:获取从 m 到 n 的子串,结果可能为空串或包含单个或
多个字符的子串
• 区间格式说明
• 下标 m 为子字符串首字符索引, n 为子字符串过尾字符索引
• 包含第 m 个字符,但不包含第 n 个字符
• 可省略 m 或 n ,默认从字符串首或至字符串尾
• 正反向索引下标可混合使用
14
字符串索引下标示例二
>>> s = "Python 程序设计 " # 注意引号的全角与半角问题
>>> print(s) # 字符串长度为十个字符
'Python 程序设计 '
>>> s[0:8] # 取前八个字符,第八号字符不
计入
'Python 程序 '
>>> s[:6] # 取前六个字符
'Python'
>>> s[6:] # 跳过前六个字符
' 程序设计 '
>>> s[:] # 字符串自身
'Python 程序设计 '
>>> s[-1:-3] # 空字符串, n 必须为 m 之后
某字符索引 15
字符串索引下标示例二
>>> s[-3:-3] # 空字符串, n 必须为 m 之后
某字符索引
''
>>> s[-3:-1] # 取倒数第三和第二个字符
' 序设 '
>>> s[-4:] # 取最后四个字符
' 程序设计 '
>>> s[:-1] # 排除末尾字符
'Python 程序设 '
>>> s[-10:2] # 取前两个字符
'Py‘
>>>

16
4.1.3  字符串操作符
• 加法:字符串合并
• 示例: x + y 表示合并两个字符串 x 与 y ,系统不添加额外空格
• 标量乘法:字符串复制
• 示例: n * x 或 x * n 表示复制 n 次字符串 x ,以构造新串
• 集合:子串从属关系运算
• 示例:若 x 为 y 的子串,则 x in y 返回 True ,否则返回
False
• 索引:返回子串
• 示例: s[i] 或 s[m : n]

17
字符串操作符示例
>>> s1 = "Python"
>>> s2 = " 程序设计 "
>>> s = s1 + s2 # 字符串合并
>>> s
'Python 程序设计 '
>>> n = 2
>>> n * s # 字符串重复
'Python 程序设计 Python 程序设计 '
>>> s * 3 # 字符串重复
'Python 程序设计 Python 程序设计 Python 程序设计 '
>>> s1 in s # 判定子串是否存在
True
>>>
18
4.1.4  字符串处理函数
• 输入输出函数(具体解释请参阅第 1.6 节)
• 函数 print() 、 input() 、 raw_input() 、 eval()
• 转换函数(具体解释请参阅第 1.4.5 节)
• 函数 int() 、 float() 、 complex() 、 bin() 、 hex() 、 oct()
• 序数函数(具体解释请参阅第 3.1.3 节)
• 函数 chr() 、 ord()
• 字符串构造与属性函数(具体解释请参阅第 3.1.3 节)
• 函数 len() 、 class str()

19
字符串处理函数示例
>>> s1 = "Python"
>>> s2 = " 程序设计 "
>>> s = s1 + s2 # 字符串合并
>>> s
'Python 程序设计 '
>>> len(s1)
6
>>> len(s2)
4
>>> len(s)
10
>>>

20
字符串处理示例
>>> n = 42
>>> n
42
>>> s = str(n)
>>> s
'42'
>>> m = -3.14
>>> m
-3.14
>>> s = str(m)
>>> s
'-3.14'
>>>
21
字符串处理示例:文本密码服务
• 凯撒密码( Caesar cipher )
• 基本原理:对称加密体制,通过将字母前后移动一定位数实现
加密和解密,位数为凯撒密码密钥
• 编写函数 Caesar_encrypt() 与 Caesar_decrypt() ,将字符串
“ Fall leaves when leaves fall.” 加密并解密
• 为简单计,仅加密英文字母,使用字母表旋转移动
• 注:文字游戏
• 英语单词回文: Fall leaves as soon as leaves fall.
• 中文翻译:落秋叶秋落,秋落叶落秋,叶落秋落叶,落叶秋叶落,叶落
秋落也……
22
字符串处理示例:文本密码服务
# 加密函数
def Carsar_encrypt(info: str, key: int) -> str:
r = ""
for c in info:
if ord("a") <= ord(c) <= ord("z"):
r += chr((ord(c) - ord("a") + key) % 26 + ord("a"))
elif ord("A") <= ord(c) <= ord("Z"):
r += chr((ord(c) - ord("A") + key) % 26 + ord("A"))
else:
r += c
return r

23
字符串处理示例:文本密码服务
# 解密函数
def Carsar_decrypt(ciphertext: str, key: int) -> str:
r = ""
for c in ciphertext:
if ord("a") <= ord(c) <= ord("z"):
r += chr((ord(c) - ord("a") - key) % 26 + ord("a"))
elif ord("A") <= ord(c) <= ord("Z"):
r += chr((ord(c) - ord("A") - key) % 26 + ord("A"))
else:
r += c
return r

24
字符串处理示例:文本密码服务
# 验证代码
s = "Fall leaves when leaves fall."

t = Carsar_encrypt(s, 3)
print("After encrypting:", t)

r = Carsar_decrypt(t, 3)
print("After decrypting:", r)

# 运行结果
After encrypting: Idoo ohdyhv zkhq ohdyhv idoo.
After decrypting: Fall leaves when leaves fall.

25
4.1.5  字符串对象方法
• 基本原则
• 无论字符串对象是否具名,均可调用字符串类的方法
• 字符特征方法
• 方法 str.endwith(suffix[, start[, end]]) :若字符串以 suffix
结尾,返回 True ,否则返回 False
• 方法 str.isalnum() :若字符全为英文字母或数字,返回
True ,否则返回 False
• 方法 str.isalpha() :若字符全为英文字母,返回 True ,否则
返回 False
26
4.1.5  字符串对象方法
• 字符特征方法
• 方法 str.isdecimal() :若字符全为十进制数字,返回 True ,
否则返回 False
• 方法 str.isdigit() :若字符全为数字,返回 True ,否则返回
False
• 方法 str.isidentifier() :若字符串为有效标识符,返回
True ,否则返回 False
• 方法 str.islower() :若字符全为小写,返回 True ,否则返回
False

27
4.1.5  字符串对象方法
• 字符特征方法
• 方法 str.isnumberic() :若字符全为数值字符(含 Unicode
字符),返回 True ,否则返回 False
• 方法 str.isprintable() :若字符全为可打印字符,返回
True ,否则返回 False
• 方法 str.isspace() :若字符全为空格,返回 True ,否则返回
False
• 方法 str.isupper() :若字符全为大写,返回 True ,否则返
回 False

28
4.1.5  字符串对象方法
• 字符特征方法
• 方法 str.startwith(prefix[, start[, end]]) :若字符串以 suffix
起始,返回 True ,否则返回 False
• 字符转换方法
• 方法 str.lower() :返回字符串副本,小写字符
• 方法 str.upper() :返回字符串副本,大写字符
• 字符串操作方法
• 方法 str.find(sub[, start[, end]]) :查找子串
• 方法 str.join(iterable) :合并字符串
29
4.1.5  字符串对象方法
• 字符串操作方法
• 方法 str.lstrip([chars]) :删除字符串起始部分字符;缺省删
除空格; chars 非前缀,而是其中所有字符组合均被删除
• 方法 str.partition(sep) :分割字符串为三元组,以 sep 首次
发生为准,三元组包括分割符前子串,分割符和分割符后子串
• 方法 str.replace(old, new[, count]) :返回字符串副本,使用
新的子串 new 替换 old ;若指定 count ,则替换前 count

• 方法 str.rfind(sub[, start[, end]]) :逆向查找子串
• 方法 str.rpartition(sep) :逆向分割字符串为三元组
30
4.1.5  字符串对象方法
• 字符串操作方法
• 方法 str.rsplit(sep = None, maxsplit = -1) :逆向分割字符串,返
回单词列表;若指定 maxsplit ,则最多分为 maxsplit + 1 个子

• 方法 str.rstrip([chars]) :逆向删除字符串部分结尾字符;缺省
删除空格; chars 非后缀,而是其中所有字符组合均被删除
• 方法 str.split(sep = None, maxsplit = -1) :分割字符串,返回单
词列表;若指定 maxsplit ,则最多分为 maxsplit + 1 个子串
• 方法 str.strip([chars]) :删除字符串部分起始和结尾字符;缺省
删除空格; chars 非后缀,而是其中所有字符组合均被删除
31
字符串对象方法示例
>>> s = " Python 程序设计 ".strip() # 删除字符串前后空格
>>> print(s)
'Python 程序设计 '
>>> s = "interesting".strip('ing') # 删除前后“ ing” 组合子串
>>> print(s)
'terest'
>>> 'a,b,c'.split(',', maxsplit=1) # 分割字符串为两个子串
['a', 'b,c']
>>> ' a b c '.split() # 缺省以空格分割字
符串
['a', 'b', 'c']
>>>

32
计算机程序设计基础( Python ) 33
4.1  字符串
4.2  字符串格式化
4.3  文 件
4.4   密码服务

第四章 文本处理 34
4.2  字符串格式化 35
4.2.1   printf 风格
4.2.2   format() 方法
4.2.1   printf 风格
• 格式: format % value
• format :待格式化字符串
• % :格式化操作符;格式化起始标志
• value :格式化值;多参数格式化时须为元组对象(数目必须
一致)或映射对象(如字典)
• 注意事项
• 容易导致问题,尽量不用此风格
• 尽量使用 str.format() 方法格式化字符串

36
4.2.1   printf 风格
• 格式化规范: %[(name)][flags][width][.precision]
[lenmod]type
• 映射键 name :可选;如有,必须至于小括号中
• 填充标志 flags :可选;仅影响部分类型
• “#” 、“ 0” 、“ ”、“ +”
• 最小场宽 width :可选;该项至少占用 width 个字符宽度
• 若为“ *” ,则实际场宽从元组下个值中获取
• 精度 precision :可选;小数点后位数;缺省值为 6
• 若为“ *” ,则实际精度从元组下个值中获取

37
4.2.1   printf 风格
• 格式化规范
• 长度修饰符 lenmod :可选;若有误,则忽略
• “h” 、“ l” 、“ L”
• 示例:“ %ld” 与“ %d” 等价
• 转换类型 type
• “d” 、“ i” :有符号十进制整数;“ o” :有符号八进制整数;“ X” 、
“ x” :有符号十六进制整数(大小写);“ E” 、“ e” :浮点数指数
形式(大小写);“ F” 、“ f” :浮点数十进制形式(大小
写);“ G” 、“ g” :浮点数格式(大小写);“ c” :单个字符;
“ r” 、“ s” 、“ a” :字符串,分别调用 repr() 、 str() 、 ascii() 转
换任意 Python 对象;“ %” :自身
38
printf 风格字符串格式化示例
>>> print('The answer is %d.' % 42)
The answer is 42.

>>> print('The %dth number is %f.' % (42, 3.14))


The 42th number is 3.140000.

>>> print('%(language)s has %(number)03d quote types.' %


... {'language': "Python", "number": 2})
...
Python has 002 quote types.

39
4.2.2   format() 方法
• 方法原型: str.format(*args, **kargs)
• 功能:格式化字符串,返回格式化后的新字符串
• 注意事项
• 调用对象为模板字符串,可包含替换字段和其他文字
• 模板字符串包含多个替换字段,用于控制替换文本位置
• 替换字段以花括号表示,其中可包含位置参数的数字索引或关
键字参数名称;如无索引,则按照实际值在 format() 方法中
的出现顺序依次替换

40
字符串格式化示例一
>>> "1 + 2 = {}".format(1 + 2)
'1 + 2 = 3'

>>> "{0} + {1} = {2}".format(1, 2, 1 + 2)


'1 + 2 = 3'

>>> "{a} + {b} = {c}".format(a = 1, b = 2, c = 1 + 2)


'1 + 2 = 3'

41
4.2.2   format() 方法
• 格式: {[index]:[[fill]align][sign][#][0][width]
[group_option][.precision][lenmod][type]}
• 格式说明
• 填充格式 fill 与 0 :前者填充任意字符,后者补 0
• 对齐标志 align
• “<” :左对齐;“ >” :右对齐;“ =” :对于数值,首位数前强制填充,
缺省时补 0 ; “ ^” :居中
• 符号标志 sign
• “+” :显示正负号;“ -” :仅显示负数符号;“ ”:正数符号位显示
空格
42
4.2.2   format() 方法
• 格式说明
• 替换形式标志 # :仅适用于数值型
• 非十进制整数显示前缀,浮点数强制显示小数点,“ g” 或“ G” 格式转
换保留尾部 0
• 场宽标志 width :指定最小显示宽度
• 分组选项标志 group_option :
• “_” :位数多时,插入千位分隔符(十进制整数和浮点数)或四字符分
隔符(二进制、八进制和十六进制整数);“ ,” :千位分隔符
• 精度标志 precision :为数值时,指定小数点后位数;非数值
时,指定最大场宽
43
4.2.2   format() 方法
• 注意事项
• 类型标志 type :指定数据表示类型
• “s” :字符串
• “b” :二进制整数;“ c” :字符;“ d” :十进制整数;“ o” :八进制
整数;“ x” :十六进制整数(小写);“ X” :十六进制整数(大写);
“ n” :十进制整数,插入分隔符
• “e” :小写指数格式浮点数,缺省精度为 6 ;“ E” :大写指数格式浮
点数,缺省精度为 6 ;“ f” :浮点数,缺省精度为 6 ;“ g” :通用
格式,根据数据情况,使用小写指数格式;“ G” :通用格式,根据数
据情况,使用大写指数格式;“ n” :与“ g” 类似,但使用预设分隔符;
“ %” :数值乘以 100 后以“ f” 格式显示百分数,后跟百分号

44
字符串格式化示例二
# 文本对齐与场宽

>>> '{:<30}'.format('left aligned')


'left aligned '

>>> '{:>30}'.format('right aligned')


' right aligned'

>>> '{:^30}'.format('centered')
' centered '

>>> '{:*^30}'.format('centered')
'***********centered***********'
45
字符串格式化示例二
# 符号

>>> '{:+f}; {:+f}'.format(3.14, -3.14)


'+3.140000; -3.140000'

>>> '{: f}; {: f}'.format(3.14, -3.14)


' 3.140000; -3.140000'

>>> '{:-f}; {:-f}'.format(3.14, -3.14)


'3.140000; -3.140000'

46
字符串格式化示例二
# 进制与分隔符

>>> "int: {0:d}; hex: {0:x}; bin: {0:b}".format(42)


'int: 42; hex: 2a; bin: 101010'

>>> "int: {0:d}; hex: {0:#x}; bin: {0:#b}".format(42)


'int: 42; hex: 0x2a; bin: 0b101010‘

>>> '{:,}'.format(1234567890)
'1,234,567,890'

47
字符串格式化示例二
# 百分比与类型特定格式

>>> points, total = 19, 22


>>> 'Correct answer: {:.2%}'.format(points / total)
'Correct answers: 86.36%'

>>> import datetime


>>> d = datetime.datetime(2017, 4, 19, 12, 15, 58)
>>> '{:%Y-%m-%d %H:%M:%S}'.format(d)
'2017-04-19 12:15:58'

>>> '{{{:s} braces here}}'.format('Curly')


'{Curly braces here}'
48
计算机程序设计基础( Python ) 49
4.1  字符串
4.2  字符串格式化
4.3  文 件
4.4   密码服务

第四章 文本处理 50
4.3  文 件 51
4.3.1  文件概述
4.3.2  文件打开与关闭
4.3.3  文件读取
4.3.4  文件写入
4.3.1  文件概述
• 文件定义
• 存储在外部介质上的信息(数据序列)
• 文件分类
• 文本文件:由单一特定编码字符串组成,如“ .txt” 文件
• 文件内容格式:多为可打印字符,信息一般分行,有分行符
• 易用性:计算机和人均容易创建、修改、阅读
• 二进制文件:由二进制字节流组成,如“ .mp4” 文件
• 文件内容格式:不同文件的二进制数据流格式不同
• 易用性:计算机容易创建、修改、阅读;人则较为困难

52
论文本文件不存在性
• 一种关注
• 世界本没有文本文件,用的人多了,就有了文本文件
• 计算机中只存在一种文件——二进制文件
• 所有文件都必须以二进制格式保存和处理
• 文本文件同样必须保存为二进制文件!
• 文件文件和二进制文件概念之本质:是否以人类旧有信息处理
方式和编码格式存储信息

53
4.3.2  文件打开与关闭
• 注意:文件是重要资源
• 操作系统能够同时访问的文件数目受限
• 对于不同操作系统或不同操作系统版本,其数值可能不同
• 操作文件是应时刻注意资源管理问题
• 访问文件时可能发生各种错误,建议使用 try…finally 封装文件操作
• 文件操作流程
• 打开文件
• 操作文件
• 关闭文件
54
打开文件
• 文件打开函数: open()
• 函数格式: open(file, mode = "r", buffering = -1, encoding =
None, errors = None, newline = None, closefd = True, opener =
None)
• 功能描述:打开 file 文件,返回文件对象,失败时引发
IOError 异常
• 函数参数
• file :字符串型或整型;文件名,可包含文件路径;与文件相
关的文件描述符(整型)

55
打开文件
• 函数参数
• mode :字符串型;可选,文件打开模式,缺省为文本文件读
模式
• buffering :整型;可选,缓冲区策略
• encoding :字符串型;可选,文件编码名称,缺省编码与平台
有关,仅适用于文本文件
• errors :字符串型;可选,指定编码错误如何处理; "strict"
时引发 ValueError , "ignore" 则忽视编码错误,但可能导
致数据丢失
• newline :字符串型;可选,设置换行符格式
56
打开文件
• 函数参数
• closefd :布尔型;可选,关闭文件时是否关闭其文件描述符,
缺省为 False ;当使用文件名打开文件时,无需提供此参数
• opener :函数型;可选,指定用于打开文件的可调用对象
• 函数返回值:文件对象,类型( io 模块)与模式有关
• 文本模式: io.TextIOWrapper 类型
• 二进制读模式: io.BufferedReader 类型
• 二进制写与追加模式: io.BufferedWriter 类型
• 二进制读写模式: io.BufferedRandom 类型
57
打开文件
• 文件打开模式
• "r" :读模式,缺省;若文件不存在,引发
FileNotFoundError 异常
• "w" :写模式;若文件不存在,创建之;若存在,覆盖式写入,
原内容擦除
• "x" :写模式;若文件不存在,创建之;若存在,引发
FileExistsError 异常
• "a" :写模式;若文件不存在,创建之;若存在,新信息追加
至文件尾部

58
打开文件
• 文件打开模式
• "b" :二进制模式
• "t" :文本模式,缺省
• "+" :读写模式;打开磁盘文件并更新
• 文件打开模式说明
• "r" 、 "w" 、 "x" 、 "a" 与 "b" 、 "t" 、 "+" 可混合使用
• "rt" :缺省模式
• "w+b" :二进制读写模式,覆盖式写入,原内容擦除
• "r+b" :二进制读写模式,原内容不擦除
59
关闭文件
• 文件关闭方法: fileobject.close()
• 功能说明:关闭文件, fileobject 为文件对象
• 文件打开与关闭示例
# 以文本读模式打开文件
ft = open(" 社会主义核心价值观 .txt", "r")
print(ft.readlines())
ft.close()
# 以二进制读模式打开文件
fb = open(" 社会主义核心价值观 .txt", "rb")
print(fb.readlines())
fb.close()

60
文件打开与关闭示例输出
[' 社会主义核心价值观 \n', ' 富强、民主、文明、和谐; \n', ' 自由、平
等、公正、法治; \n', ' 爱国、敬业、诚信、友善。 \n']
[b'\xc9\xe7\xbb\xe1\xd6\xf7\xd2\xe5\xba\xcb\xd0\xc4\xbc\
xdb\xd6\xb5\xb9\xdb\r\n', b'\xb8\xbb\xc7\xbf\xa1\xa2\xc3\
xf1\xd6\xf7\xa1\xa2\xce\xc4\xc3\xf7\xa1\xa2\xba\xcd\xd0\
xb3\xa3\xbb\r\n', b'\xd7\xd4\xd3\xc9\xa1\xa2\xc6\xbd\xb5\
xc8\xa1\xa2\xb9\xab\xd5\xfd\xa1\xa2\xb7\xa8\xd6\xce\xa3\
xbb\r\n', b'\xb0\xae\xb9\xfa\xa1\xa2\xbe\xb4\xd2\xb5\xa1\
xa2\xb3\xcf\xd0\xc5\xa1\xa2\xd3\xd1\xc9\xc6\xa1\xa3\r\n']

61
4.3.3  文件读取
• 文件读取方法
• 方法 fileobject.readall() :读取文件全部内容,返回字符串或
字节流
• 方法 fileobject.read(size = -1) :读取文件全部内容,返回字符
串或字节流;若提供参数 size ,则仅读取前 size 个字符
• 方法 fileobject.readline(size = -1) :读取文件一行内容,返回
字符串或字节流;若提供参数 size ,则仅读取前 size 个字符
• 方法 fileobject.readlines(sizehint = -1) :读取文件全部行,返
回行列表对象;若提供参数 sizehint ,则近似读取前 sizehint
个字符;此参数为建议值,可能会被忽略
62
文件读取示例:第一版
• 读取文件全部行并输出
# 注意:本程序未处理任何异常

# 以文本读模式打开文件
f = open(" 社会主义核心价值观 .txt", "rt")

# 读取全部文本行,并逐行打印
for line in f.readlines():
print(line)

# 关闭文件
f.close()

63
文件读取示例:第二版
• 读取文件全部行并输出,要求处理文件读写异常,确保
文件资源被正确释放
f = open(" 社会主义核心价值观 .txt", "rt")
try:
# 读取全部文本行,并逐行打印
# readlines() 读入全部文本行,文件太大时处理效率较低或无法处理
for line in f.readlines():
print(line)
finally:
# 关闭文件
f.close()

64
文件读取示例:第三版
• 读取文件全部行并输出,要求处理文件读写异常,确保
文件资源被正确释放
f = open(" 社会主义核心价值观 .txt", "rt")
try:
# 读取全部文本行,并逐行打印
# 将文件对象本身做为文本行序列,遍历之
for line in f:
print(line)
finally:
# 关闭文件
f.close()

65
插播: with 语句
• 语句格式
• with context_expression [as target]:
with_suite
• 目的与意义
• 类似异常处理机制,替代 try…finally 以简化代码
• 对资源访问进行有效控制
• 资源访问期间无论是否发生异常都执行清理操作,确保释放资源
• 典型应用场合
• 文件使用后自动关闭之;多线程编程时自动获取和释放锁

66
插播: with 语句
• 语句说明
• 计算 context_expression ,返回上下文管理器对象
• 自动调用 context_expression.__enter__() 方法进入上下文
• 返回值赋给 target (若存在)
• 目标变量 target 既可以是单个量,也可以是元组(必须使用小括号
对)
• 执行语句体 with_suite
• 无论执行语句体时是否发生异常,都自动调用
context_expression.__exit__() 方法退出上下文

67
插播: with 语句
• 相关术语
• 上下文管理协议( Context Management Protocol )
• 包含方法 __enter__() 和方法 __exit__()
• 支持本协议的对象必须实现此两个方法
• 上下文管理器( Context Manager )
• 支持上下文管理协议的对象
• 上下文管理器定义执行 with 语句时要建立的运行时上下文,负责执行
with 语句块进入与退出上下文操作
• 通常用 with 语句调用上下文管理器,也可直接调用其方法

68
插播: with 语句
• 相关术语
• 运行时上下文( runtime context )
• 由上下文管理器创建,通过上下文管理器方法 __enter__() 和方法
__exit__() 实现
• 上下文表达式( Context Expression )
• 关键字 with 之后表达式,返回上下文管理器对象
• 语句体( with-body )
• 执行语句体前,自动调用上下文管理器方法 __enter__()
• 执行语句体后,自动调用上下文管理器方法 __exit__()

69
文件读取示例:第四版
• 读取文件全部行并输出,要求使用 with 语句处理文
件读写异常,确保文件资源被正确释放
# 使用 with 语句进行文件资源管理,使用上下文管理器打开文件
with open(" 社会主义核心价值观 .txt", "rt") as f:
# 读取全部文本行,并逐行打印
# 将文件对象本身做为文本行序列,遍历之
for line in f:
print(line)
# Python 已内置文件操作上下文,下述代码因此可省略,由系统自动调用
# f.close()

70
4.3.4  文件写入
• 文件写入方法
• 方法 fileobject.write(s) :向文件中写入字符串或字节流
• 方法 fileobject.writeline(lines) :将字符串列表写入文件;参
数 lines 为待写入的字符串列表对象
• 方法 fileobject.seek(offset) :改变文件操作位置;参数 offset
取值: 0 (文件头部)、 1 (当前位置)、 2 (文件尾部)

71
文件写入示例
• 将下述两首词写入文件,写入时输出第一首词作
《望江南 超然台作》 《临江仙 夜归临皋》
  ——苏 轼   ——苏 轼

春未老,风细柳斜斜。 夜饮东坡醒复醉,归来仿佛三更。
试上超然台上望,半壕春水一城花。 家童鼻息已雷鸣。
烟雨暗千家。 敲门都不应,倚杖听江声。

寒食后,酒醒却咨嗟。 长恨此身非我有,何时忘却营营。
休对故人思故国,且将新火试新茶。 夜阑风静縠纹平。
诗酒趁年华。 小舟从此逝,江海寄馀生。

72
文件写入示例
# -*- coding: utf-8 -*-

ci_1 = " 《望江南 超然台作》 \n" \


"   ——苏 轼 \n\n" \
" 春未老,风细柳斜斜。 \n" \
" 试上超然台上望,半壕春水一城花。 \n" \
" 烟雨暗千家。 \n\n" \
" 寒食后,酒醒却咨嗟。 \n" \
" 休对故人思故国,且将新火试新茶。 \n" \
" 诗酒趁年华。 \n\n"

73
文件写入示例
ci_2 = " 《临江仙 夜归临皋》 \n" \
"   ——苏 轼 \n\n" \
" 夜饮东坡醒复醉,归来仿佛三更。 \n" \
" 家童鼻息已雷鸣。 \n" \
" 敲门都不应,倚杖听江声。 \n\n" \
" 长恨此身非我有,何时忘却营营。 \n" \
" 夜阑风静縠纹平。 \n" \
" 小舟从此逝,江海寄馀生。 \n\n"

# 控制标志:是否显示详细提示信息
verbose = True

74
文件写入示例
def show(info):
print(" 正在写入: \n\n" + info + "\n 写入完毕。 \n"
if verbose else " 写入完毕。 \n")

def write_to_file(filename, info, notify = None):


with open(filename, "a+") as f:
f.write(info)
if notify:
notify(info)

75
文件写入示例
def main() -> int:
filename = input(" 请输入文件名: ") + ".txt"
write_to_file(filename, ci_1, notify = show)
write_to_file(filename, ci_2)
return 0

main()

76
计算机程序设计基础( Python ) 77
4.1  字符串
4.2  字符串格式化
4.3  文 件
4.4   密码服务

第四章 文本处理 78
4.4  密码服务 79
4.4.1  密码学概述
4.4.2  安全哈希模块
4.4.3  消息认证模块
4.4.4  秘密模块
4.4.1  密码学概述
• 密码学( cryptology , cryptography )
• 定义:研究编制密码和破译密码的技术科学
• 意义:将人们能读懂的消息(明文, plain text )变换成不易
读懂的信息(密文, ciphertext )以隐藏信息内容,使窃听者
无法理解消息内容,同时又能让合法用户把变换结果还原成原
始消息
• 密码学发展史
• 古典密码:是艺术,而非科学
• 典型密码有阴符、藏头诗、石蜡密信、反切密码(明代戚继光)、凯撒
密码和天书等
80
4.4.1  密码学概述
• 密码学发展史
• 近代密码: 1949 年成为学科
• 香农( Claude Elwood Shannon ):《保密系统的通信理论》和《通信
的数学理论》
• 现代密码学: 1976 年,美国国家标准局公布数据加密标准
( DES )
• DES 为对称密码标准,在世界上广泛流传和应用
• 密码学家、图灵奖获得者 Diffie 和 Hellman ( 2016 年图灵奖)发表
《密码学的新方向》,开创公钥密码学新纪元

81
4.4.2  安全哈希模块
• 安全哈希算法: hashlib 库
• 功能:安全哈希( secure hash )算法和消息摘要( message
digest )算法的通用接口
• 已实现: FIPS 安全哈希算法:
SHA1 、 SHA224 、 SHA256 、 SHA384 、 SHA512
• 已实现: RSA MD5 算法

82
哈希算法构造函数
• 常用构造函数
• 构造函数 sha1() 、 sha224() 、 sha256() 、 sha384() 、 sha512()
、 blake2b() 、 blake2s() 等
• MD5 构造函数
• 构造函数 md5()
• 附加构造函数
• 构造函数 sha3_224() 、 sha3_256() 、 sha3_384() 、 sha3_512()
、 shake_128() 、 shake_256() 等

83
常数与哈希对象
• 常用常数
• 常数 hashlib.digest_size :结果哈希值大小,以字节为单位
• 常数 hashlib.block_size :哈希算法内部块大小,以字节为单位
• 哈希对象常用属性
• 属性 hash.name :哈希算法标准名称
• 哈希对象常用方法
• 方法 hash.update(arg) :更新哈希对象
• 方法 hash.digest() :返回数据摘要
• 方法 hash.hexdigest() :返回十六进制数据摘要
84
安全哈希模块示例
>>> import hashlib
>>> m = hashlib.sha256()
>>> m.update(b"You cann't swallow a cage, can you?")
>>> m.update(b" But you can cage a swallow, cann't you?")
>>> m.digest()
b'\xbc,\x82\xa8\xa8\x83-\xd4r4q\xbf\xb2\xcb\x98\xdf<$e\t>\tNR_\
x8f\xf6\xbe00hc'
>>> m.hexdigest()
'bc2c82a8a8832dd4723471bfb2cb98df3c2465093e094e525f8ff6be3030686
3'
>>> m.digest_size
32
>>> m.block_size
64

85
4.4.3  消息认证模块
• 基于密钥哈希的消息认证: hmac 库
• 功能:利用哈希算法,以一个密钥和一个消息为输入,生成一
个消息摘要作为输出
• 常用常数、属性与方法
• 与安全哈希库类似

86
4.4.4  秘密模块
• 秘密模块: secrets 库
• 功能:用于生成加密级的强安全随机数,以管理密码、账户认
证、安全令牌( token )等秘密信息
• 常用函数
• 类 secrets.SystemRandom :操作系统提供的高质量随机数生
成器
• 函数 secrets.choice(sequence) :返回非空序列中随机元素
• 函数 secrets.randbelow(n) :返回 [0, n) 中随机整数
• 函数 secrets.randbits(k) :返回 k 位随机整数
87
秘密模块示例
• 编写函数,返回十位字符的随机密码,至少包括一位大
写字母,一位小写字母和三位数字
def password() -> str:
import string, secrets
alphabet = string.ascii_letters + string.digits
while True:
pwd = ''.join(secrets.choice(alphabet) for i in range(10))
if (any(c.islower() for c in pwd) and
any(c.isupper() for c in pwd) and
sum(c.isdigit() for c in pwd) >= 3):
return pwd

88
计算机程序设计基础( Python ) 89
作 业 90
• 习题一 编写函数 is_word_palindrome() ,判断某个给定的英文字符串是否
为单词回文,非英文单词内容全部忽略,要求英文字符串从文件中读取。
• 习题二 按月输出本年日历,星期日在前。
• 习题三 将上述日历输出至文件 。
• 习题四 挑战性问题:以四行三列的月份格式打印全年日历,即同时输出第
一季度三个月日历后,紧接着输出第二季度三个月日历。

You might also like