【python】列表、元组、字典和文件
·
目录
1、 列表是什么,元组是什么
编程中
,
经常需要使用变量
,
来保存
/
表示数据
.
如果代码中需要表示的数据个数比较少
,
我们直接创建多个变量即可
.
num1 = 10num2 = 20num3 = 30......
但是有的时候
,
代码中需要表示的数据特别多
,
甚至也不知道要表示多少个数据
.
这个时候
,
就需要用到列表.
列表是一种让程序猿在代码中批量表示
/
保存数据的方式
就像我们去超市买辣条, 如果就只是买一两根辣条, 那咱们直接拿着辣条就走了.但是如果一次买个十根八根的, 这个时候用手拿就不好拿, 超市老板就会给我们个袋子.这个袋子, 就相当于 列表
元组和列表相比
,
是非常相似的
,
只是列表中放哪些元素可以修改调整
,
元组中放的元素是创建元组的时候
就设定好的
,
不能修改调整
.
列表就是买散装辣条, 装好了袋子之后, 随时可以把袋子打开, 再往里多加辣条或者拿出去一些辣条.元组就是买包装辣条, 厂家生产好了辣条之后, 一包就是固定的这么多, 不能变动了.
1.1 创建列表
- 创建列表主要有两种方式. [ ] 表示一个空的列表.
alist = [ ]alist = list ()print ( type ( alist ))
- 如果需要往里面设置初始值, 可以直接写在 [ ] 当中.
可以直接使用
print
来打印
list
中的元素内容
.
alist = [1, 2, 3, 4]
print(alist)
- 列表中存放的元素允许是不同的类型. (这一点和 C++ Java 差别较大).
alist = [1, 'hello', True]
print(alist)
因为
list
本身是
Python
中的内建函数
,
不宜再使用
list
作为变量名
,
因此命名为
alist
1.2 访问下标
- 可以通过下标访问操作符 [ ] 来获取到列表中的任意元素.
我们把
[ ]
中填写的数字
,
称为
下标
或者
索引
.
alist = [1, 2, 3, 4]
print(alist[2])
注意
:
下标是从
0
开始计数的
,
因此下标为
2 ,
则对应着
3
这个元素
.
- 通过下标不光能读取元素内容, 还能修改元素的值.
alist = [1, 2, 3, 4]
alist[2] = 100
print(alist)
- 如果下标超出列表的有效范围, 会抛出异常.
alist = [1, 2, 3, 4]
print(alist[100])
- 因为下标是从 0 开始的, 因此下标的有效范围是 [0, 列表长度 - 1]. 使用 len 函数可以获取到列表的元素个数.
alist = [1, 2, 3, 4]
print(len(alist))
- 下标可以取负数. 表示 "倒数第几个元素"
alist = [1, 2, 3, 4]
print(alist[3])
print(alist[-1])
alist[-1]
相当于
alist[len(alist) - 1]
1.3 切片操作
通过下标操作是一次取出里面第一个元素
.
通过切片
,
则是一次取出一组连续的元素
,
相当于得到一个
子列表
- 使用 [ : ] 的方式进行切片操作.
alist = [1, 2, 3, 4]
print(alist[1:3])
alist[1:3] 中的 1:3 表示的是 [1, 3) 这样的由下标构成的前闭后开区间.也就是从下标为 1 的元素开始(2), 到下标为 3 的元素结束(4), 但是不包含下标为 3 的元素.所以最终结果只有 2, 3
- 切片操作中可以省略前后边界
alist = [1, 2, 3, 4]
print(alist[1:]) # 省略后边界, 表示获取到列表末尾
print(alist[:-1]) # 省略前边界, 表示从列表开头获取
print(alist[:]) # 省略两个边界, 表示获取到整个列表.
- 切片操作还可以指定 "步长" , 也就是 "每访问一个元素后, 下标自增几步“
alist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(alist[::1])
print(alist[::2])
print(alist[::3])
print(alist[::5])
- 切片操作指定的步长还可以是负数, 此时是从后往前进行取元素. 表示 "每访问一个元素之后, 下标自减几步"
alist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(alist[::-1])
print(alist[::-2])
print(alist[::-3])
print(alist[::-5])
如果切片中填写的数字越界了
,
不会有负面效果
.
只会尽可能的把满足条件的元素过去到
.
alist = [1, 2, 3, 4]
print(alist[100:200])
1.4 遍历列表元素
"
遍历
"
指的是把元素一个一个的取出来
,
再分别进行处理
.
- 最简单的办法就是使用 for 循环
alist = [1, 2, 3, 4]
for elem in alist:
print(elem)
- 也可以使用 for 按照范围生成下标, 按下标访问
alist = [1, 2, 3, 4]
for i in range(0, len(alist)):
print(alist[i])
- 还可以使用 while 循环. 手动控制下标的变化
alist = [1, 2, 3, 4]
i = 0
while i < len(alist):
print(alist[i])
i += 1
1.5 新增元素
- 使用 append 方法, 向列表末尾插入一个元素(尾插).
alist = [1, 2, 3, 4]
alist.append('hello')
print(alist)
- 使用 insert 方法, 向任意位置插入一个元素
insert
第一个参数表示要插入元素的下标
.
alist = [1, 2, 3, 4]
alist.insert(1, 'hello')
print(alist)
PS: 什么是 "方法" (method)方法其实就是函数. 只不过函数是独立存在的, 而方法往往要依附于某个 "对象".像上述代码 alist.append , append 就是依附于 alist, 相当于是 "针对 alist 这个列表, 进行尾插操作".
1.6 查找元素
- 使用 in 操作符, 判定元素是否在列表中存在. 返回值是布尔类型.
alist = [1, 2, 3, 4]
print(2 in alist)
print(10 in alist)
使用
index
方法
,
查找元素在列表中的下标
.
返回值是一个整数
.
如果元素不存在
,
则会抛出异常
.
alist = [1, 2, 3, 4]
print(alist.index(2))
print(alist.index(10))
1.7 删除元素
- 使用 pop 方法删除最末尾元素
alist = [1, 2, 3, 4]
alist.pop()
print(alist)
- pop 也能按照下标来删除元素
alist = [1, 2, 3, 4]
alist.pop(2)
print(alist)
使用
remove
方法
,
按照值删除元素
.
alist = [1, 2, 3, 4]
alist.remove(2)
print(alist)
1.8 连接列表
- 使用 + 能够把两个列表拼接在一起.
此处的
+
结果会生成一个新的列表
.
而不会影响到旧列表的内容
.
alist = [1, 2, 3, 4]
blist = [5, 6, 7]
print(alist + blist)
- 使用 extend 方法, 相当于把一个列表拼接到另一个列表的后面.
a.extend(b)
,
是把
b
中的内容拼接到
a
的末尾
.
不会修改
b,
但是会修改
a.
alist = [1, 2, 3, 4]
blist = [5, 6, 7]
alist.extend(blist)
print(alist)
print(blist)
1.9 关于元组
元组的功能和列表相比
,
基本是一致的
.
元组使用
( )
来表示
.
atuple = ( )
atuple = tuple()
元组不能修改里面的元素
,
列表则可以修改里面的元素
因此
,
像读操作
,
比如访问下标
,
切片
,
遍历
, in, index, +
等
,
元组也是一样支持的
.
但是
,
像写操作
,
比如修改元素
,
新增元素
,
删除元素
, extend
等
,
元组则不能支持
.
另外
,
元组在
Python
中很多时候是默认的集合类型
.
例如
,
当一个函数返回多个值的时候
.
def getPoint():
return 10, 20
result = getPoint()
print(type(result))
此处的
result
的类型
,
其实是元组
.
问题来了
,
既然已经有了列表
,
为啥还需要有元组
?
元组相比于列表来说, 优势有两方面:你有一个列表, 现在需要调用一个函数进行一些处理. 但是你有不是特别确认这个函数是否会把你的列表数据弄乱. 那么这时候传一个元组就安全很多.我们马上要讲的字典, 是一个键值对结构. 要求字典的键必须是 "可hash对象" (字典本质上也是一个hash表). 而一个可hash对象的前提就是不可变. 因此元组可以作为字典的键, 但是列表不行.
1.10 小结
列表和元组都是日常开发最常用到的类型
.
最核心的操作就是根据
[ ]
来按下标操作
.
在需要表示一个
"
序列
"
的场景下
,
就可以考虑使用列表和元组
.
如果元素不需要改变
,
则优先考虑元组
.
如果元素需要改变
,
则优先考虑列表
.
二、字典
2.1 字典是什么
字典是一种存储
键值对
的结构
.
啥是
键值对
?
这是计算机
/
生活中一个非常广泛使用的概念
.
把 键
(key)
和 值
(value)
进行一个一对一的映射
,
然后就可以根据键
,
快速找到值
.
举个栗子 , 学校的每个同学 , 都会有一个唯一的学号 .知道了学号 , 就能确定这个同学 .此处 " 学号 " 就是 " 键 ", 这个 " 同学 " 就是 " 值 ".
2.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',
}
2.3 查找key
- 使用 in 可以判定 key 是否在 字典 中存在. 返回布尔值.
student = {
'id': 1,
'name': 'zhangsan',
}
print('id' in student)
print('score' in student)
- 使用 [ ] 通过类似于取下标的方式, 获取到元素的值. 只不过此处的 "下标" 是 key. (可能是整数, 也可能是字符串等其他类型).
student = {
'id': 1,
'name': 'zhangsan',
}
print(student['id'])
print(student['name'])
- 如果 key 在字典中不存在, 则会抛出异常.
student = {
'id': 1,
'name': 'zhangsan',
}
print(student['score'])
2.4 新增/修改元素
使用
[ ]
可以根据
key
来新增
/
修改
value.
- 如果 key 不存在, 对取下标操作赋值, 即为新增键值对
student = {
'id': 1,
'name': 'zhangsan',
}
student['score'] = 90
print(student)
- 如果 key 已经存在, 对取下标操作赋值, 即为修改键值对的值.
student = {
'id': 1,
'name': 'zhangsan',
'score': 80
}
student['score'] = 90
print(student)
2.5 删除元素
- 使用 pop 方法根据 key 删除对应的键值对.
student = {
'id': 1,
'name': 'zhangsan',
'score': 80
}
student.pop('score')
print(student)
2.6 遍历字典元素
- 直接使用 for 循环能够获取到字典中的所有的 key, 进一步的就可以取出每个值了.
student = {
'id': 1,
'name': 'zhangsan',
'score': 80
}
for key in student:
print(key, student[key])
2.7 取出所有key和value
- 使用 keys 方法可以获取到字典中的所有的 key
student = {
'id': 1,
'name': 'zhangsan',
'score': 80
}
print(student.keys())
此处 dict_keys 是一个特殊的类型, 专门用来表示字典的所有 key. 大部分元组支持的操作对于dict_keys 同样适用.
- 使用 values 方法可以获取到字典中的所有 value
student = {
'id': 1,
'name': 'zhangsan',
'score': 80
}
print(student.values())
此处 dict_values 也是一个特殊的类型, 和 dict_keys 类似.
- 使用 items 方法可以获取到字典中所有的键值对.
student = {
'id': 1,
'name': 'zhangsan',
'score': 80
}
print(student.items())
2.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 }))
2.9 小结
字典也是一个常用的结构
.
字典的所有操作都是围绕
key
来展开的
.
需要表示
"
键值对映射
"
这种场景时就可以考虑使用字典
.
三、文件
3.1 文件是什么
变量是把数据保存到内存中
.
如果程序重启
/
主机重启
,
内存中的数据就会丢失
.
要想能让数据被持久化存储
,
就可以把数据存储到硬盘中
.
也就是在
文件
中保存
.
在
Windows "
此电脑
"
中
,
看到的内容都是 文件
.
通过文件的后缀名
,
可以看到文件的类型
.
常见的文件的类型如下
:
- 文本文件 (txt)
- 可执行文件 (exe, dll)
- 图片文件 (jpg, gif)
- 视频文件 (mp4, mov)
- office 文件 (.ppt, docx)
- ......
3.2 文件路径
一个机器上
,
会存在很多文件
,
为了让这些文件更方面的被组织
,
往往会使用很多的
"
文件夹
"(
也叫做
目录
)来整理文件.
实际一个文件往往是放在一系列的目录结构之中的
.
为了方便确定一个文件所在的位置
,
使用
文件路径
来进行描述
.
- D: 表示 盘符. 不区分大小写.
- 每一个 \ 表示一级目录. 当前 QQ.exe 就是放在 "D 盘下的 program 目录下的 qq 目录下的 Bin 目录中" .
- 目录之间的分隔符, 可以使用 \ 也可以使用 / . 一般在编写代码的时候使用 / 更方便.
上述以 盘符 开头的路径, 我们也称为 绝对路径.除了绝对路径之外, 还有一种常见的表示方式是 相对路径. 相对路径需要先指定一个基准目录, 然后以基准目录为参照点, 间接的找到目标文件. 咱们课堂上暂时不详细介绍.描述一个文件的位置, 使用 绝对路径 和 相对路径 都是可以的. 对于新手来说, 使用 绝对路径 更简单更好理解, 也不容易出错.
3.3 文件操作
要使用文件
,
主要是通过文件来保存数据
,
并且在后续把保存的数据读取出来
.
但是要想读写文件
,
需要先
"
打开文件
",
读写完毕之后还要
"
关闭文件
".
3.3.1 打开文件
使用内建函数
open
打开一个文件
.
f = open('d:/test.txt', 'r')
- 第一个参数是一个字符串, 表示要打开的文件路径
- 第二个参数是一个字符串, 表示打开方式. 其中 r 表示按照读方式打开. w 表示按照写方式打开. a表示追加写方式打开.
- 如果打开文件成功, 返回一个文件对象. 后续的读写文件操作都是围绕这个文件对象展开.
- 如果打开文件失败(比如路径指定的文件不存在), 就会抛出异常.
3.3.2 关闭文件
使用
close
方法关闭已经打开的文件
.
f.close()
使用完毕的文件要记得及时关闭
!
一个程序能同时打开的文件个数
,
是存在上限的
.
flist = []
count = 0
while True:
f = open('d:/test.txt', 'r')
flist.append(f)
count += 1
print(f'count = {count}')
如上面代码所示, 如果一直循环的打开文件, 而不去关闭的话, 就会出现上述报错.当一个程序打开的文件个数超过上限, 就会抛出异常.注意: 上述代码中, 使用一个列表来保存了所有的文件对象. 如果不进行保存, 那么 Python 内置的垃圾回收机制, 会在文件对象销毁的时候自动关闭文件.但是由于垃圾回收操作不一定及时, 所以我们写代码仍然要考虑手动关闭, 尽量避免依赖自动关闭.
3.3.3 写文件
文件打开之后
,
就可以写文件了
.
- 写文件, 要使用写方式打开, open 第二个参数设为 'w'
- 使用 write 方法写入文件.
f = open('d:/test.txt', 'w')
f.write('hello')
f.close()
用记事本打开文件, 即可看到文件修改后的内容.
- 如果是使用 'r' 方式打开文件, 则写入时会抛出异常.
f = open('d:/test.txt', 'r')
f.write('hello')
f.close()
- 使用 'w' 一旦打开文件成功, 就会清空文件原有的数据.
- 使用 'a' 实现 "追加写", 此时原有内容不变, 写入的内容会存在于之前文件内容的末尾.
f = open('d:/test.txt', 'w')
f.write('hello')
f.close()
f = open('d:/test.txt', 'a')
f.write('world')
f.close()
- 针对已经关闭的文件对象进行写操作, 也会抛出异常.
f = open('d:/test.txt', 'w')
f.write('hello')
f.close()
f.write('world')
3.3.4 读文件
- 读文件内容需要使用 'r' 的方式打开文件
- 使用 read 方法完成读操作. 参数表示 "读取几个字符"
f = open('d:/test.txt', 'r')
result = f.read(2)
print(result)
f.close()
如果文件是多行文本
,
可以使用
for
循环一次读取一行
.
先构造一个多行文件
.
f = open('d:/test.txt', 'r')
for line in f:
print(f'line = {line}')
f.close()
注意: 由于文件里每一行末尾都自带换行符, print 打印一行的时候又会默认加上一个换行符, 因此打印结果看起来之间存在空行.使用 print(f'line = {line}', end='') 手动把 print 自带的换行符去掉.
- 使用 readlines 直接把文件整个内容读取出来, 返回一个列表. 每个元素即为一行.
f = open('d:/test.txt', 'r')
lines = f.readlines()
print(lines)
f.close()
3.3.5 关于中文的处理
当文件内容存在中文的时候
,
读取文件内容不一定就顺利
.可能出现乱码
计算机表示中文的时候
,
会采取一定的编码方式
,
我们称为
"
字符集
"
所谓 "编码方式" , 本质上就是使用数字表示汉字.我们知道, 计算机只能表示二进制数据. 要想表示英文字母, 或者汉字, 或者其他文字符号, 就都要通过编码.最简单的字符编码就是 ascii. 使用一个简单的整数就可以表示英文字母和阿拉伯数字.但是要想表示汉字, 就需要一个更大的码表.一般常用的汉字编码方式, 主要是 GBK 和 UTF-8
必须要保证文件本身的编码方式
,
和
Python
代码中读取文件使用的编码方式匹配
,
才能避免出现上述问题.
Python3 中默认打开文件的字符集跟随系统, 而 Windows 简体中文版的字符集采用了 GBK, 所以如果文件本身是 GBK 的编码, 直接就能正确处理.如果文件本身是其他编码(比如 UTF-8), 那么直接打开就可能出现上述问题
使用记事本打开文本文件
,
在
"
菜单栏
" -> "
文件
" -> "
另存为
"
窗口中
, 可以看到当前文件的编码方式.
- 如果此处的编码为 ANSI , 则表示 GBK 编码.
- 如果此处为 UTF-8 , 则表示 UTF-8 编码.
此时修改打开文件的代码
,
给
open
方法加上
encoding
参数
,
显式的指定为和文本相同的字符集
,
问题即可解决.
f = open('d:/test.txt', 'r', encoding='utf8')
字符编码问题, 是编程中一类比较常见, 又比较棘手的问题. 需要对于字符编码有一定的理解, 才能从容应对.
3.4 使用上下文管理器
打开文件之后
,
是容易忘记关闭的
. Python
提供了
上下文管理器
,
来帮助程序猿自动关闭文件
.
- 使用 with 语句打开文件.
- 当 with 内部的代码块执行完毕后, 就会自动调用关闭方法
with open('d:/test.txt', 'r', encoding='utf8') as f:
lines = f.readlines()
print(lines)
更多推荐



所有评论(0)