Python 中内置的三种常用数据结构: 列表 (list), 元组(tuple) 和字典 (dict). 这三种数据结构可用于保存多个数据项, 可以保存大量数据. 列表和元组是按顺序存放元素, 每个元素有自己的索引, 可通过索引访问元素, 两者的区别在于, 元组是不可修改的, 列表可以修改. 字典以 key-value(键值对) 形式保存数据. 这三种数据结构是编程中必不可少的内容.
一, 序列介绍
序列是指一种包含多项数据的数据结构, 序列包含的多个数据项 (也叫成员) 按顺序排列, 可通过索引来访问成员.
常见的序列类型有: 字符串, 列表, 元组. 字符串和元组序列类型是不可变的, 一旦创建就不能修改其所包含的成员. 列表是可变序列, 程序可以修改列表序列中的元素. 在实际运用时, 如果保存固定个数的数据项, 而不需要修改时, 就应该使用元组.
列表创建: 使用方括号, 元素之间用英文逗号分隔. 也可将可迭代对象传递给内置函数 list()来创建.
元组创建: 使用圆括号, 元素之间用英文逗号分隔. 也可将可迭代对象传递给内置函数 tuple()来创建.
二, 列表和元组的通用方法
只要不涉及到改变元素的操作, 列表和元组的用法是通用的.
1, 通过索引使用元素
列表和元组的索引都是从 0 开始, 第 1 个元素的索引为 0, 第 2 个元素的索引为 1,......, 以此类推; 还可以使用负数索引, 倒数第 1 个元素的索引为 - 1, 倒数第 2 个元素的索引为 - 2,......, 以此类推.
列表的元素相当于一个变量, 程序可使用它的值, 也可对元素赋值; 元组的元素相当于一个常量, 程序只能使用它的值, 不能重新赋值.
示例如下:
- name = ('python', 'c', 'java', 'go', 'linux') # 定义一个元组
- print(name) # 输出整个元组
- print(name[0]) # 访问元组第 1 个元素
- print(name[1]) # 访问元组第 2 个元素
- print(name[-1]) # 访问元组倒数第 1 个元素
- print(name[-2]) # 访问元组倒数第 2 个元素
上面通过索引访问元组的方法同样适用于列表.
2, 子序列
字符串可通过切片获取一个子串, 列表和元组同样也可使用索引获取中间一段, 该方法中叫作 slice(分片或切片), 语法格式如下:
[start: end: step]
start 和 end 两个索引可以使用正数或负数, 负数表示从倒数开始. 语法表示从 start 索引开始(包含), 到 end 索引结束(不包含).
step 表示步长, 也可使用负数. 示例如下:
- name = ['python', 'c', 'java', 'go', 'linux'] # 定义一个列表
- print(name[2:4]) # 访问第 3 个到第 5 个 (不包含) 索引间的元素, 输出:['java', 'go']
- print(name[-3:-1]) # 访问倒数第 3 个到倒数第 1 个间的元素, 输出:['java', 'go']
- print(name[1:-2]) # 访问从第 2 个到倒数第 2 个间的元素, 输出:['c', 'java']
- print(name[1:4:2]) # 访问从第 2 个到第 5 个(不包含), 间隔为 2 的元素, 输出:['c', 'go']
- print(name[::-1]) # 反转列表
上面对列表进行切片的操作, 同样适用于元组.
3, 列表和元组的加法运算
列表和列表相加, 元组和元组相加, 不能直接将列表和元组相加.
- a_tuple = (1, 2)
- b_tuple = (3, 4)
- sum_tuple = a_tuple + b_tuple # 两个元组相加后, a_tuple 和 b_tuple 并没有任何改变
- print(sum_tuple) # 输出:(1, 2, 3, 4)
- # a_tuple + [10, 20] # 元组和列表相加, 报 TypeError 错误.
- print([10, 20] + ['a', 'b']) # 计算两个列表相加, 输出:[10, 20, 'a', 'b']
4, 列表和元组的乘法运算
列表和元组可以和整数 N 相乘, 得到的结果是列表和元组的元素重复 N 次. 示例如下:
- print([1, 'a'] * 3) # 输出:[1, 'a', 1, 'a', 1, 'a']
- print(('a', 'z') * 3) # 输出:('a', 'z', 'a', 'z', 'a', 'z')
列表和元组可以同时使用加法, 乘法. 一个简单示例如下:
- # 创建一个表示一个月 31 天中的后缀字符元组, 对于 1,2,3 是 st,nd,rd, 其他使用 th 代表.
- order_endings = ('st', 'nd', 'rd') + \
- ('th',) * 17 + ('st', 'nd', 'rd') \
- + ('th',) * 7 + ('st',)
- print(order_endings)
- day = input("输入日期(1-31):")
- day_int = int(day)
- print(day + order_endings[day_int - 1])
在这个示例中 order_endings 得到一个合并后的元组, 要注意 ('th',) 的写法, 当元组只有一个元素时, 要在这个唯一的元素后面加英文逗号, 不加英文逗号就表示的是字符串, 字符串和元组不能相加. 运行示例如下:
输入日期(1-31):28
28th
5,in 运算符
in 运算符用于判断列表或元组是否包含某个元素, 判断结果是 bool 型值. 示例如下:
- a_tuple = ('python', 'java', 'c++')
- print('java' in a_tuple) # 输出: True
- print('go' in a_tuple) # 输出: False
6, 长度, 最大值和最小值
Python 内置的 len(),max(),min() 全局函数可用于获取列表或元组的长度, 最大值和最小值. 其中 max(),min() 要对元组, 列表中的元素比较大小, 因此传给 max(),min()函数的元组, 列表的元素必须是相同类型并且可以比较大小. 示例如下:
- a_tuple = (100, 33, 88, 50, 106) # 数字类型元组, 每个元素类型相同
- print(len(a_tuple)) # 计算长度, 输出: 5
- print(max(a_tuple)) # 计算最大值, 输出: 106
- print(min(a_tuple)) # 计算最小值, 输出: 33
- b_list = ['Python', 'Java', 'Linux', '世界'] # 字符串类型的列表, 每个元素类型相同
- print(len(b_list)) # 计算长度, 输出: 4
- print(max(b_list)) # 计算最大值, 输出: 世界
- print(min(b_list)) # 计算最小值, 输出: Java
由上面示例可知, Python 中字符串是可以比较大小的, 按照字符串中每个字符对应的编码来比较字符串的大小.
7, 序列封包和序列解包
序列封包 (Sequence Packing) 和序列解包 (Sequence Unpacking) 功能, 可支持下面两种赋值方式.
(1), 程序把多个值赋给一个变量时, Python 会自动将多个值封装成元组. 这种功能叫做序列封包.
(2), 程序允许将序列 (字符串, 元组, 列表等) 直接赋值给多个变量, 此时序列的各元素会被依次赋值给每个变量(要求序列的元素个数和变量个数相等). 这种功能叫做序列解包.
示例如下:
- res = 1, 2, 3 # 序列封包, 封包成一个元组赋值给 res 变量
- print(res) # 输出是序列:(1, 2, 3)
- print(type(res)) # 查看类型是元组类型, 输出:<class 'tuple'>
- x, y, z = res # 序列解包, 序列中的元素依次赋值给 x,y,z 三个变量
在赋值时同时使用了序列封包和序列解包机制, 可让赋值运算符同时将多个值赋给多个变量, 例如:
x, y, z = 10, 20, 30
上面这行代码实际执行过程是:
(1), 先执行序列封包
xyz = 10, 20, 30
(2), 再执行序列解包
x, y, z = xyz
使用这种语法可实现交换变量的值, 例如:
x, y, z = y, z, x
序列解包时, 也可只解出部分, 就是剩下的依然使用列表变量保存. 使用这种方式解包时, 可以在左边被赋值的变量之前添加 "*", 这个变量就代表一个列表, 可以保存多个集合元素. 示例如下:
- first, second, *REST = range(10)
- print(first) # 输出: 0
- print(second) # 输出: 1
- print(REST) # 输出:[2, 3, 4, 5, 6, 7, 8, 9]
- *_, last = range(10) # 解包时保存最后一个元素, 其它元素丢弃
- first, *middle, last = range(10) # 保存第一个和最后一个元素, 中间元素统一保存到列表中
三, 使用列表
元组不可变, 列表是可变的. 元组支持的操作, 列表基本上都支持; 列表支持对元素的修改, 而元组不支持. 如果程序不修改元素, 可使用元组替代列表会更安全. 另外, 同样元素的列表和元组, 元组占用的内存空间要小一些.
1, 创建列表
创建列表可用方括号, 也可用内置的 list() 函数来创建, list() 函数可用于将元组, 区间 (range) 等对象转换为列表. 示例如下:
- a_tuple = ('python', 'java', 'go') # 创建元组
- a_list = list(a_tuple) # 使用 list() 函数将元组转列表
- print(a_list) # 输出是列表:['python', 'java', 'go']
- print(range(5)) # 区间是一个可迭代对象, 输出: range(0, 5)
- print(list(range(5))) # 使用 list() 函数将区间转换为列表, 输出:[0, 1, 2, 3, 4]
区间函数 range() 有 3 个参数, 分别是 start, stop, step. 省略 start 参数时, 默认从 0 开始, stop 参数是区间的结尾, 不能省略, 在计算区间时不包含结尾. step 参数是步长, 省略时默认为 1, 该参数可以是负数. 在 Python2 中的 xrange() 函数与 Python3 版本中的 range() 相同, 在 Python2 中的 range() 函数返回的是列表.
创建元组也有相应的内置函数 tuple(), 该函数可用于将列表, 区间 (range) 等对象转换为元组. 示例如下:
- a_list = ['python', 'java', 'go']
- a_tuple = tuple(a_list) # 使用 tuple() 函数将列表转换为元组
- b_tuple = tuple(range(10, 1, -2)) # 将区间对象转换为元组
2, 增加列表元素, append(),extend(),insert() 方法
列表的 append() 方法可把传入的参数追加到列表的最后面. append() 方法可接收单个值参数, 也可接收元组, 列表等参数, 但是接收的元组, 列表会当成单个元素, 这样会形成在列表中嵌套列表, 嵌套元组的情形. 示例如下:
- a_list = [1, '2', 3]
- a_list.append('a') # 在列表中追加元素
- print(a_list) # 输出是:[1, '2', 3, 'a']
- a_list.append((4, '5')) # 追加一个元组, 元组被当成一个元素
- print(a_list) # 输出是:[1, '2', 3, 'a', (4, '5')]
- a_list.append([6, '7']) # 追加列表, 列表被当成一个元素
- print(a_list) # 输出是:[1, '2', 3, 'a', (4, '5'), [6, '7']]
如果不希望列表, 元组当成整体被追加到列表中, 只是追加列表中的所有元素, 则可使用 extend() 方法. 示例如下:
- b_list = [1, '2']
- b_list.extend((3, '4')) # 参数是元组, 但追加的仍是元组中的所有元素
- print(b_list) # 输出是:[1, '2', 3, '4']
- b_list.extend([5, '6']) # 追加列表中的所有元素
- print(b_list) # 输出是:[1, '2', 3, '4', 5, '6']
- b_list.extend(range(8, 10)) # 还可以追加区间中的所有元素
- print(b_list) # 输出是:[1, '2', 3, '4', 5, '6', 8, 9]
在列表的指定位置插入元素, 可使用 insert() 方法, 示例如下:
- c_list = [1, 2, 3, 4]
- c_list.insert(2, 'p') # 在索引 2 处插入字符串
- print(c_list) # 输出是:[1, 2, 'p', 3, 4]
- c_list.insert(2, tuple('py')) # 在索引 2 处插入一个元组, 元组被当成一个元素
- print(c_list) # 输出是:[1, 2, ('p', 'y'), 'p', 3, 4]
3, 删除列表元素, del,remove()方法, clear()方法
del 语句是 Python 的一种语句, 专用于删除操作, 不仅可用于删除列表的元素, 还可用于删除变量等.
del 语句可删除列表中的单个元素, 也可直接删除列表的中间一段, 示例如下:
- a_list = [1, 'a', 2, 'b']
- del a_list[2] # 删除列表第 3 个元素
- print(a_list) # 输出是:[1, 'a', 'b']
- del a_list[1:3] # 通过列表切片, 可一次性删除多个元素, 切片还可以设定步长
del 语句还可删除普通变量, 示例如下:
- name = 'michael'
- del name # 删除 name 变量
- print(name) # 报错: NameError
remove() 方法删除列表元素时, 不根据索引来删除元素, 而是根据元素本身来删除. 只删除在列表中第一个找到的元素. 如果在列表中未找到要删除的元素, 则报 ValueError 错误. 示例如下:
- c_list = [10, 'python', 20, 'java', 20, 'go', 'python']
- c_list.remove(20) # 删除第一次找到的元素
- print(c_list) # 输出:[10, 'python', 'java', 20, 'go', 'python']
clear() 方法表示清空列表的所有元素. 示例如下:
- c_list.clear()
- print(c_list) # 输出空列表:[]
4, 修改列表元素
列表的元素可看做是变量, 程序可对列表的元素赋值, 这样就达到修改列表元素. 通过索引对列表元素赋值, 索引可以是正数索引, 也可以是负数索引. 还可以通过切片语法对列表中某一部分赋值, 使用切片操作时, 新赋值的元素个数可以不等于原来的元素个数. 这相当于在给列表增加或删除元素. 示例如下:
- d_list = list(range(1,5))
- d_list[2] = 30 # 修改列表单个元素的值, 结果:[1, 2, 30, 4]
- d_list[1] = [10, 20] # 修改列表, 结果:[1, [10, 20], 30, 4]
- d_list[-1] = 40 # 修改列表最后一个元素的值, 结果:[1, [10, 20], 30, 40]
- d_list[1:3] = ('a', 'b', 'c') # 通过切片索引修改, 切片末尾不包含, 结果:[1, 'a', 'b', 'c', 40]
列表的切片索引中的起始索引和结束索引相等时, 切片的结果是空列表, 利用这个特性, 可为列表插入元素.
- d_list[2:2] = ['x', 'y'] # 切片起始索引等于结束索引, 结果是在列表中指定位置插入元素
- print(d_list) # 输出是:[1, 'a', 'x', 'y', 'b', 'c', 40]
如果将列表中某一段赋值为空列表, 就变成从列表中删除元素.
d_list[2:5] = [] # 结果是 2,3,4 的元素被删除:[1, 'a', 'c', 40]
当对切片赋值单个值时, 如果这个值是字符串, Python 会把这个字符串当成序列处理, 字符串的每个字符都是一个元素. 如下示例:
- d_list[1:3] = 'python' # 对切片赋值字符串, 结果:[1, 'p', 'y', 't', 'h', 'o', 'n', 40]
- d_list[1:3] = 100 # 对切片赋值一个数字常量, 会报错: TypeError
使用切片赋值时, 还可指定 step 参数, 如果指定 step 参数, 则要求所赋值的列表元素个数与所替换的列表个数相等. 如下所示:
- d_list[1: 6: 2] = [10, 20, 30]
- print(d_list) # 输出是:[1, 10, 'y', 20, 'h', 30, 'n', 40]
5, 列表的其他常用方法
列表的方法中还有很多以双下划线开头的方法, 这些方法有特殊意义, 不建议使用. 除这些双下划线方法外, 列表可用的方法可在命令行使用 dir(list) 查看.
- dir(list) # 剔除双下划线方法后, 输出如下:
- ['append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
这些方法中还有一些前面未说过的, 同样是常用的方法:
(1),count()方法: 统计列表中某个元素出现的次数.
(2),index()方法: 判断某个元素在列表中出现的位置, 如果该元素不在列表中, 报 ValueError 错误.
(3),pop()方法: 将列表中最后一个元素取出, 相当于出栈. 默认取出列表最后一个元素.
(4),reverse()方法: 反转列表, 将列表中的元素反向存放.
(5),sort()方法: 用于对列表元素排序.
(1), count()方法使用
- a_list = [10, 20, [10, 20], 20, 30]
- print(a_list.count(20)) # 统计 20 在列表中出现的次数, 不统计在嵌套列表中出现的次数, 输出: 2
- print(a_list.count([10, 20])) # 输出: 1
(2),index() 方法使用
index()方法查找某个元素在列表中的出现的位置, 如果该元素没有出现, 则报 ValueError 错误. 该方法还可以传入 start,end 参数, 用于在列表指定的范围内搜索元素. 示例如下:
- print(a_list.index(20)) # 查找元素 20 第一次出现的位置, 输出: 1
- print(a_list.index(20, 2)) # 从索引 2 开始, 查找元素 20 第一次出现的位置.
- print(a_list.index(10, 1, 4)) # 在索引 1 到索引 4 之间找元素 10 第一次出现的位置, 找不到, 报: ValueError
(3), pop() 方法使用
列表的 pop() 方法可实现元素出栈功能. 栈是一种特殊数据结构, 可实现先进后出 (FILO,First in Last out) 和 先进先出 (FIFO,First in First out) 功能. 在其他编程语言中, 有一个入栈方法 push(), 在 Python 中可使用 append 代替 push() 方法.
pop()方法从列表取出元素后, 会返回取出的元素, 并且列表中相应的元素被移除. 示例如下:
- stack = ['a', 'b']
- stack.append('c') # 入栈一个元素
- print(stack.pop()) # 出栈一个元素, 默认取出列表最后一个元素, 输出: c
- print(stack) # 此时的列表已经没有 c 这个元素, 输出:['a', 'b']
- print(stack.pop(0)) # 传递索引给 pop() 方法, 取出指定的元素, 输出: a
(4), reverse()方法使用
reverse()方法反转列表中的所有元素顺序, 该方法会对列表进行就地修改. 示例如下:
- a_list = list(range(5))
- a_list.reverse() # 反转列表中的元素顺序
- print(a_list) # 输出:[4, 3, 2, 1, 0]
- a_list[::-1] # 使用切片索引也能反转列表, 但不会就地修改原列表
(5), sort() 方法使用
列表的 sort() 方法默认对列表的元素按大小排序, 默认是从小到大 (升序) 排序. 传递参数 reverse=True 时, 表示从大到小排序. 还可以传递 key 参数改变排序方式, key 参数需要的是一个函数名, 排序的方式由这个函数的功能决定. 示例如下:
- num_list = [5, -2, 7, -9, 11]
- num_list.sort() # 默认排序, 从小到大
- print(num_list) # 输出:[-9, -2, 5, 7, 11]
- num_list.sort(reverse=True) # 传递参数 reverse=True 改变默认排序, 从大到小排序
- str_list = ['pyt', 'go', 'java', '走你, python']
- str_list.sort() # 对字符串元素排序, 默认按字符串包含的字符的编码来比较大小
- print(str_list) # 输出:['go', 'java', 'pyt', '走你, python']
- str_list.sort(key=len) # 给 key 参数传递函数名 len, 表示元素长度排序
- print(str_list) # 输出:['go', 'pyt', 'java', '走你, python']
- str_list.sort(key=len, reverse=True) # 长度从大到小排序
- print(str_list) # 输出:['走你, python', 'java', 'pyt', 'go']
在 Python2 中列表的 sort() 方法可传入一个比较大小的函数, 该函数负责比较列表元素的大小. 该函数有两个参数, 该函数返回正整数时表示第一个参数大于第二个参数; 返回负整数时, 表示函数第一个参数小于第二个参数; 返回 0 时, 表示两个参数相等. 示例如下:
- # 在 Python2 中执行
- def len_cmp(x, y):
- '''定义一个根据长度比较大小的函数'''
- return 1 if len(x)> len(y) else (-1 if len(x) < len(y) else 0)
- str_list.sort(len_cmp)
- print(str_list) # 输出:['go', 'pyt', 'java', '走你, python']
part3-1 Python 列表和元组(列表和元组常用方法使用, 序列封包和解包)
来源: http://www.bubuko.com/infodetail-3200056.html