1. 字典
1.1 字典是什么
字典是一种存储键值对的结构。
键值对是计算机/生活中一个非常广泛使用的概念。
把 键(key) 和 值(value) 进行一个一对一的映射, 然后就可以根据键, 快速找到值。
1.2 创建字典
- 创建一个空的字典,使用 { } 表示字典
a = { } b = dict() print(type(a)) print(type(b))
- 创建字典的时候设置初始值
键值对之间使用 , 分割, 键和值之间使用 : 分割. (冒号后面推荐加一个空格)。
使用 print 来打印字典内容。student = {'id': 1, 'name': 'zhangsan'} print(student)
- 为了代码更规范美观, 在创建字典的时候往往会把多个键值对, 分成多行来书写
student = { 'id': 1, 'name': 'zhangsan' }
- 最后一个键值对, 后面可以写 , 也可以不写
student = { 'id': 1, 'name': 'zhangsan', }
1.3 查找 key
- 使用 in 可以判定 key 是否在 字典 中存在. 返回布尔值
not in 是 in 的反操作student = { 'id': 1, 'name': 'zhangsan' } print('id' in student) print('score' in student) print('id' not in student) print('score' not in student)
- 使用 [ ] 来根据 key 获取得到 value
student = { 'id': 1, 'name': 'zhangsan' } print(student['id']) print(student['name'])
- 如果 key 在字典中不存在, 则会抛出异常
student = { 'id': 1, 'name': 'zhangsan' } print(student['score'])
1.4 新增/修改元素
使用 [ ] 可以根据 key 来新增/修改 value
- 如果 key 不存在, 对取下标操作赋值, 即为新增键值对
student = { 'id': 1, 'name': 'zhangsan' } student['score'] = 90 print(student)
- 如果 key 已经存在, 对取下标操作赋值, 即为修改键值对的值
student = { 'id': 1, 'name': 'zhangsan', 'score': 90 } student['score'] = 100 print(student)
1.5 删除元素
使用 pop 方法根据 key 删除对应的键值对。
student = {
'id': 1,
'name': 'zhangsan',
'score': 90
}
student.pop('score')
print(student)
1.6 遍历字典元素
直接使用 for 循环能够获取到字典中的所有的 key, 进一步的就可以取出每个值了。
student = {
'id': 1,
'name': 'zhangsan',
'score': 90
}
for key in student:
print(key, student[key])
1.7 取出所有 key 和 value
- 使用 keys 方法可以获取到字典中的所有 key
student = { 'id': 1, 'name': 'zhangsan', 'score': 90 } print(student.keys())
此处 dict_keys 是一个特殊的类型, 专门用来表示字典的所有 key。大部分元组支持的操作对于dict_keys 同样适用。
- 使用 values 方法可以获取到字典中的所有 value
student = { 'id': 1, 'name': 'zhangsan', 'score': 90 } print(student.values())
此处 dict_values 也是一个特殊的类型, 和 dict_keys 类似。
- 使用 items 方法可以获取到字典中的所有键值对
student = { 'id': 1, 'name': 'zhangsan', 'score': 90 } print(student.items())
此处 dict_items 也是一个特殊的类型, 和 dict_keys 类似。
1.8 合法的 key 类型
不是所有的类型都可以作为字典的 key。
字典本质上是一个哈希表,哈希表的 key 要求是 “可哈希的”,也就是可以计算出一个哈希值。
- 可以使用 hash 函数计算某个对象的哈希值
- 但凡能够计算除哈希值的类型,都可以作为字典的 key
- 不可变的对象,一般是可哈希的
- 可变的对象,一般是不可哈希的
print(hash(0))
print(hash(3.14))
print(hash('hello'))
print(hash(True))
print(hash(())) # () 是一个空的元组
- 列表无法计算哈希值
print(hash([1, 2, 3]))
- 字典也无法计算哈希值
print(hash({'id': 1}))
小结
字典也是一个常用的结构. 字典的所有操作都是围绕 key 来展开的.
需要表示 “键值对映射” 这种场景时就可以考虑使用字典
2. 文件
2.1 文件是什么
变量是把数据保存到内存中. 如果程序重启/主机重启, 内存中的数据就会丢失。
要想能让数据被持久化存储, 就可以把数据存储到硬盘中,也就是在文件中保存。
在 Windows ->此电脑 中看到的内容都是文件
通过文件的后缀名, 可以看到文件的类型. 常见的文件的类型如下:
- 文本文件 (txt)
- 可执行文件 (exe, dll)
- 图片文件 (jpg, gif)
- 视频文件 (mp4, mov)
- office 文件 (.ppt, docx)
我们这里主要研究最简单的文本文件。
2.2 文件路径
一个机器上, 会存在很多文件, 为了让这些文件更方面的被组织, 往往会使用很多的 “文件夹”(也叫做目录) 来整理文件。实际一个文件往往是放在一系列的目录结构之中的.。为了方便确定一个文件所在的位置, 使用 文件路径 来进行描述。
例如,上述截图中的 python-3.10.5-amd64.exe 这个文件,描述这个文件的位置,就可以使用路径 D:\A-Bit\软件\Python环境\python-3.10.5-amd64.exe 来表示。
- D:表示盘符,不区分大小写。
- 每一个 \ 表示一级目录,当前 python-3.10.5-amd64.exe 就是放在 “ D 盘下的 A-Bit 目录下的 软件 目录下的 Python环境目录中”。
- 目录之间的分隔符,可以使用 \ 也可以使用 / ,一般在编写代码的时候使用 / 更方便。
上述以 盘符 开头的路径, 我们也称为 绝对路径.。
除了绝对路径之外, 还有一种常见的表示方式是 相对路径。 相对路径需要先指定一个基准目录, 然后以基准目录为参照点, 间接的找到目标文件. 这里暂时不详细介绍.。
描述一个文件的位置, 使用 绝对路径 和 相对路径 都是可以的。 对于新手来说, 使用 绝对路径 更简单更好理解, 也不容易出错.
2.3 文件操作
要使用文件,只要是通过文件来保存数据,并且在后续把保存的数据读取出来。但是要想读写文件,需要先“打开文件”,读写完毕之后还要“关闭文件”。
2.3.1 打开文件
使用内建函数 open 打开一个文件
f = open('d:/A-Bit/code/test.txt', 'r')
- 第一个参数是一个字符串,表示要打开的文件路径。
- 第二个参数是一个字符串,表示要打开的方式。
其中:
r 表示按照读方式打开
w 表示按照写方式打开
a 表示追加写方式打开 - 如果打开文件成功,返回一个文件对象,后续的读写文件操作都是围绕这个文件对象展开。
- 如果打开文件失败(比如路径指定的文件不存在),就会抛出异常。
2.3.2 关闭文件
使用 close 方法关闭已经打开的文件。
使用完毕的文件一定要记得及时关闭!
f.close()
一个程序能同时打开的文件个数, 是存在上限的。
flist = [] count = 0 while True: f = open('d:/A-Bit/code/test.txt', 'r') flist.append(f) count += 1 print(f'count = {count}')
上面代码所示, 如果一直循环的打开文件, 而不去关闭的话, 就会出现上述报错。当一个程序打开的文件个数超过上限, 就会抛出异常。
注意: 上述代码中, 使用一个列表来保存了所有的文件对象。如果不进行保存, 那么 Python 内置的垃圾回收机制, 会在文件对象销毁的时候自动关闭文件。但是由于垃圾回收操作不一定及时, 所以我们写代码仍然要考虑手动关闭, 尽量避免依赖自动关闭。
2.3.3 写文件
文件打开后就可以写文件了
- 写文件,要是有写的方式打开,open 第二个参数设为 ‘w’
- 使用 write 方式写入文件
f = open('d:/A-Bit/code/test.txt', 'w') f.write('hello') f.close()
用记事本打开文件,即可看到文件里写入了 hello
- 如果使用 ‘r’ 方式打开文件,则会写入时抛出异常
f = open('d:/A-Bit/code/test.txt', 'r') f.write('hello') f.close()
- 使用 ‘w’ 一旦打开文件成功, 就会清空文件原有的数据。
- 使用 ‘a’ 实现 “追加写”, 此时原有内容不变, 写入的内容会存在于之前文件内容的末尾。
f = open('d:/A-Bit/code/test.txt', 'w') f.write('hello') f.close() f = open('d:/A-Bit/code/test.txt', 'a') f.write('world') f.close()
- 针对已经关闭的文件对象进行写操作, 也会抛出异常。
f = open('d:/A-Bit/code/test.txt', 'w') f.write('helli') f.close() f.write('world')
2.3.4 读文件
读文件内容需要使用 ‘r’ 的方式打开文件
- 使用 read 方法完成读操作,参数表示 “读取几个字符”
f = open('d:/A-Bit/code/test.txt', 'r')
result = f.read(2)
print(result)
f.close()
关于中文的处理
当文件内存在中文的时候,读取文件内容不一定顺利。
上述的代码,有的执行可能会出现异常
也有的可能会出现乱码。
计算机表示中文的时候,会采用一定的编码方式,我们称为“字符集”
所谓的“编码方式”,本质上就是使用数字表示汉字。
我们知道, 计算机只能表示二进制数据。 要想表示英文字母, 或者汉字, 或者其他文字符号, 就都要通过编码。
- 最简单的字符编码就是 ASCII. 使用一个简单的整数就可以表示英文字母和阿拉伯数字。
- 但是要想表示汉字, 就需要一个更大的码表。一般常用的汉字编码方式, 主要是 GBK 和 UTF-8
必须要保证文件本身的编码方式, 和 Python 代码中读取文件使用的编码方式匹配, 才能避免出现上述问题。
- Python3 中默认打开文件的字符集跟随系统, 而 Windows 简体中文版的字符集采用了 GBK, 所以
- 如果文件本身是 GBK 的编码, 直接就能正确处理.
- 如果文件本身是其他编码(比如 UTF-8), 那么直接打开就可能出现上述问题。
查看文件的编码方式:
- 使用记事本打开文本文件, 在 “菜单栏” -> “文件” -> “另存为” 窗口中, 可以看到当前文件的编码方式。
- 直接在文件内容的右下方也能看到当前文件的编码方式。
如果此处的编码为 ANSI , 则表示 GBK 编码。
如果此处为 UTF-8 , 则表示 UTF-8 编码。此时修改打开文件的代码, 给 open 方法加上 encoding 参数, 显式的指定为和文本相同的字符集, 问题即可解决.
f = open('d:/A-Bit/code/test.txt', 'r', encoding='utf8')
f = open('d:/A-Bit/code/test.txt', 'r', encoding='utf8')
result = f.read(2)
print(result)
f.close()
- 如果文件是多行文本, 可以使用 for 循环一次读取一行。
先构造一个多行的文件
f = open('d:/A-Bit/code/test.txt', 'r', encoding='utf8')
for line in f:
print(f'line = {line}')
f.close()
注意: 由于文件里每一行末尾都自带换行符, print 打印一行的时候又会默认加上一个换行符, 因此打印结果看起来之间存在空行。
用 print(f’line = {line}‘, end=’') 手动把 print 自带的换行符去掉.
f = open('d:/A-Bit/code/test.txt', 'r', encoding='utf8')
for line in f:
print(f'line = {line}', end='')
f.close()
- 使用 readlines 直接把文件整个内容读取出来, 返回一个列表. 每个元素即为一行。
f = open('d:/A-Bit/code/test.txt', 'r', encoding='utf8')
lines = f.readlines()
print(lines)
f.close()
此处的 \n 即为换行符。
2.4 使用上下文管理器
打开文件之后, 是容易忘记关闭的。 Python 提供了 上下文管理器 , 来帮助程序猿自动关闭文件。
- 使用 with 语句打开文件。
- 当 with 内部的代码块执行完毕后, 就会自动调用关闭方法。
with open('d:/A-Bit/code/test.txt', 'r', encoding='utf8')as f:
line = f.readlines()
print(line)
本章到这里就结束啦,如果有哪里写的不好的地方,请指正。
如果觉得不错并且对你有帮助的话请给个三连支持一下吧!
Fighting!!!✊