第5章 容器数据类型
5.1 序列
1)什么是序列
序列(Sequence)是一种基本且核心的数据结构,它允许我们以有序的方式存储和操作数据。序列可以包含不同类型的元素,并且支持通过索引来访问和修改这些元素。
常见的序列类型包括:列表(List)、元组(Tuple)、字符串(String)。
2)序列的操作
- 索引:
sequence[0] - 切片:
sequence[1:3] - 相加:
sequence1 + sequence2 - 乘法:
sequence * 3 - 检查成员:
x in sequence - 计算长度:
len(sequence) - 计算最大值、最小值:
max(sequence)、min(sequence)
5.2 列表List
- 列表是一个可变的、有序的元素集合。
- 列表使用
[]定义,数据之间使用,分隔。 - 列表中每个元素都有对应的位置值,称为索引或下标,索引从 0 开始向后逐个递增,并且从末尾从 -1 开始逐个向前递减。
- 列表中元素可以是不同的类型。
5.2.1 创建列表
list1 = [100, 200, 300, 400, 500]
5.2.2 访问列表
1)通过索引获取列表中元素
list1 = [100, 200, 300, 400, 500]
print(list1[1]) # 200
print(list1[-2]) # 400
2)列表切片
list1 = [100, 200, 300, 400, 500]
print(list1) # 取全部元素
print(list1[:]) # 复制整个列表
print(list1[2:4]) # 取索引从2开始到4(不包含)的元素
print(list1[2:]) # 取索引从2开始到末尾的元素
print(list1[:2]) # 取索引从0开始到2(不包含)的元素
print(list1[2:-1]) # 取索引从2开始到-1(不包含)的元素
print(list1[::-1]) # 倒序取元素
5.2.3 向列表中添加元素
list1 = [100, 200, 300, 400, 500]
list1.append(600) # 在列表末尾追加元素
list1.insert(2, 700) # 在列表指定的位置追加元素
print(list1)
5.2.4 列表相加
list1 = [100, 200, 300]
list2 = ["a", "b", "c"]
print(list1 + list2) # [100, 200, 300, 'a', 'b', 'c']
5.2.5 列表乘法
list1 = [100, 200, 300]
print(list1 * 2) # [100, 200, 300, 100, 200, 300]
5.2.6 修改列表中元素
1)通过下标修改
list1 = [100, 200, 300, 400, 500]
list1[0] = -1
print(list1)
2)通过切片修改
list1 = [100, 200, 300, 400, 500]
list1[2:4] = ["a", "b", "c"]
print(list1)
5.2.7 检查成员是否为列表中元素
list1 = [100, 200, 300]
print(100 in list1) # True
5.2.8 获取列表长度
list1 = [100, 200, 300]
print(len(list1)) # 3
5.2.9 求列表中元素的最大值、最小值、加和
list1 = [100, 200, 300, 400, 500]
print(max(list1)) # 500
print(min(list1)) # 100
print(sum(list1)) # 1500
5.2.10 遍历列表
1)直接遍历列表元素
list1 = [100, 200, 300, 400, 500]
for i in list1:
print(i)
2)通过下标遍历列表
list1 = [100, 200, 300, 400, 500]
for i in range(len(list1)):
print(i, list1[i])
3)使用 enumerate() 同时获取列表的下标和元素
list1 = [100, 200, 300, 400, 500]
for i, val in enumerate(list1):
print(i, val)
5.2.11 删除列表指定位置元素或者切片
list1 = [100, 200, 300, 400, 500]
del list1[2]
print(list1)
5.2.12 嵌套列表
列表中元素可以为列表。
list1 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for inner_list in list1:
print(inner_list)
5.2.13 列表推导式
列表推导式是 Python 中一种简洁创建列表的方式,它将一个可迭代对象的元素通过某种运算或条件筛选后生成一个新的列表。
(1)基础的列表推导式
squares = [x**2 for x in range(5)]
print(squares) # [0, 1, 4, 9, 16]
(2)带条件的列表推导式
squares = [x**2 for x in range(10) if x % 2 == 0]
print(squares) # [0, 4, 16, 36, 64]
(3)使用现有列表的列表推导式
list1 = [1, 2, 3, 4, 5]
squares = [x**2 for x in list1]
print(squares) # [1, 4, 9, 16, 25]
(4)包含多个循环的列表推导式
list1 = [1, 2, 3, 4, 5]
list2 = ["a", "b", "c", "d", "e"]
tuple_list = [(i, j) for i in list1 for j in list2]
print(tuple_list)
5.2.14 zip() 函数
zip() 函数可将多个可迭代对象中对应元素打包为一个个元组。
list1 = [1, 2, 3, 4, 5]
list2 = ["a", "b", "c", "d", "e"]
zipped = zip(list1, list2)
print(list(zipped))
5.2.15 常用函数
| 函数 | 说明 |
|---|---|
list.insert(index, x) | 在指定位置插入 x |
list.append(x) | 在列表末尾追加 x |
list1.extend(list2) | 在列表1的末尾追加列表2的数据 |
del list[index] | 删除指定位置的数据或切片 |
list.remove(x) | 删除第一次出现的 x |
list.pop([index]) | 删除指定位置的数据,默认为末尾数据 |
list.clear() | 清空列表中元素 |
list[index] = x | 修改指定位置的数据 |
list1[start:end] = list2 | 修改列表切片的数据 |
sorted(list[, reverse=True]) | 返回排序后的新列表,可选降序 |
list.sort([reverse=True]) | 对列表就地排序,可选降序 |
list.reverse() | 反转列表中的元素 |
list.index(x[, start[, end]]) | 返回 x 在列表中首次出现的位置 |
list.count(x) | 返回 x 的数量 |
len(list) | 返回列表元素个数 |
max(list) | 返回列表中最大值 |
min(list) | 返回列表中最小值 |
sum(list) | 返回列表中所有元素和 |
list.copy() | 拷贝列表 |
list(x) | 将序列转换为列表 |
5.3 字符串String
- 字符串是不可变的、有序的。
- 字符串中元素不可修改。
- 字符串使用单引号、双引号或三重引号定义。
- 字符串中每个值都有对应的位置值,称为索引或下标,索引从 0 开始向后逐个递增,并且从末尾从 -1 开始逐个向前递减。
5.3.1 创建字符串
str1 = "hello world"
5.3.2 访问字符串
str1 = "hello world"
print(str1[0])
print(str1[-1])
print(str1[4:-3])
5.3.3 字符串相加
str1 = "hello world"
str2 = "dlrow olleh"
print(str1 + str2) # hello worlddlrow olleh
5.3.4 字符串乘法
str1 = "hello world"
print(str1 * 2) # hello worldhello world
5.3.5 检查成员是否为字符串中元素
str1 = "hello world"
print("lo" in str1) # True
5.3.6 原始字符串
所有的字符串按照字面意思处理,没有转义字符。需在字符串前加上 r / R。
print("hello\nworld")
print(r"hello\nworld")
5.3.7 常用函数
| 函数 | 说明 |
|---|---|
str.replace(old, new[, max]) | 把字符串中的 old 替换成 new,可指定最大替换次数 |
str.split([x][, n]) | 按 x 分隔字符串,默认按空白字符分隔,可指定最大分隔次数 |
str.rsplit([x][, n]) | 与 split() 类似,从右边开始分隔 |
x.join(seq) | 以 x 作为分隔符,将序列中所有字符串合并为一个新字符串 |
str.strip([x]) | 截掉字符串两边的空格或指定字符 |
str.lstrip([x]) | 截掉字符串左边的空格或指定字符 |
str.rstrip([x]) | 截掉字符串右边的空格或指定字符 |
str.removeprefix() | 截掉字符串指定前缀 |
str.removesuffix() | 截掉字符串指定后缀 |
str.upper() | 将所有字符转为大写 |
str.lower() | 将所有字符转为小写 |
str.swapcase() | 反转字符串中字母大小写 |
str.capitalize() | 将字符串第一个字母变为大写,其他字母变为小写 |
str.title() | 将字符串每个单词首字母大写 |
str.casefold() | 返回适合无大小写比较的字符串版本 |
len(str) | 返回字符串长度 |
max(str) | 返回字符串中最大值 |
min(str) | 返回字符串中最小值 |
str.find(x[, start][, end]) | 返回第一个 x 的索引值,不存在返回 -1 |
str.rfind(x[, start][, end]) | 与 find() 类似,从右边开始查找 |
str.index(x[, start][, end]) | 返回第一个 x 的索引值,不存在则报错 |
str.rindex(x[, start][, end]) | 与 index() 类似,从右边开始查找 |
str.count(x[, start][, end]) | 返回字符串中 x 的个数 |
str.startswith(x[, start][, end]) | 检查字符串是否以 x 开头 |
str.endswith(x[, start][, end]) | 检查字符串是否以 x 结尾 |
str.isspace() | 检查字符串是否非空且只包含空白 |
5.3.8 其他函数
| 函数 | 说明 |
|---|---|
str.center(width[, x]) | 返回长度为 width 且居中的字符串,空白使用 x 填充 |
str.ljust(width[, x]) | 返回长度为 width 且左对齐的字符串 |
str.rjust(width[, x]) | 返回长度为 width 且右对齐的字符串 |
str.zfill(width) | 返回长度为 width 且右对齐的字符串,空白用 0 填充 |
str.splitlines([keepends]) | 按行分隔字符串,返回列表 |
str.partition(x) | 使用 x 将字符串分隔为 3 部分 |
str.rpartition(x) | 与 partition() 类似,从右边开始分隔 |
str.encode(encoding='UTF-8', errors='strict') | 对字符串使用指定格式编码 |
str.expandtabs([tabsize]) | 将字符串中 \t 转化为空格 |
str.format_map(dict) | 使用字典等映射关系来格式化字符串 |
str.isalnum() | 检查是否非空且只包含字母和数字 |
str.isalpha() | 检查是否非空且只包含字母 |
str.isascii() | 检查是否只包含 ASCII 字符 |
str.isdecimal() | 检查是否非空且只包含十进制字符 |
str.isdigit() | 检查是否非空且只包含数字 |
str.isidentifier() | 检查是否是有效的标识符 |
str.isupper() | 检查区分大小写的字符是否都是大写 |
str.islower() | 检查区分大小写的字符是否都是小写 |
str.isnumeric() | 检查是否非空且只包含数值字符 |
str.isprintable() | 检查字符串是否可打印 |
str.istitle() | 检查是否符合 title 格式 |
str.maketrans(str1, str2[, str3]) | 生成翻译表供 translate() 使用 |
str.translate() | 使用给定的翻译表替换字符串中的每个字符 |
5.4 元组Tuple
- 元组是一个不可变的、有序的元素集合。
- 不能对元组中的元素进行修改操作。
- 元组使用
()定义,数据之间使用,分隔。 - 元组中每个元素都有对应的位置值,称为索引或下标。
- 元组中元素可以是不同的类型。
- 元组的使用方式与列表类似。
5.4.1 创建元组
tuple1 = (100, 200, 300, 400, 500)
元组中只包含一个元素时,需要在元素后面添加逗号,否则括号会被当作运算符使用:
tuple1 = (100,)
也可以通过元组推导式创建元组:
tuple_generator = (x for x in range(10)) # 获取生成器对象
print(tuple_generator)
tuple1 = tuple(tuple_generator) # 转换为元组
print(tuple1)
5.4.2 访问元组
tuple1 = (100, 200, 300, 400, 500)
print(tuple1[2])
print(tuple1[-1])
print(tuple1[2:4])
5.4.3 元组相加
tuple1 = (100, 200, 300)
tuple2 = ("a", "b", "c")
print(tuple1 + tuple2) # (100, 200, 300, 'a', 'b', 'c')
5.4.4 元组乘法
tuple1 = (100, 200, 300)
print(tuple1 * 2) # (100, 200, 300, 100, 200, 300)
5.4.5 检查成员是否为元组中元素
tuple1 = (100, 200, 300, 400, 500)
print(300 in tuple1) # True
5.4.6 获取元组长度
tuple1 = (100, 200, 300, 400, 500)
print(len(tuple1)) # 5
5.4.7 求元组中元素的最大值、最小值、加和
tuple1 = (100, 200, 300, 400, 500)
print(max(tuple1)) # 500
print(min(tuple1)) # 100
print(sum(tuple1)) # 1500
5.4.8 遍历元组
tuple1 = (100, 200, 300, 400, 500)
for i in tuple1:
print(i)
for i in range(len(tuple1)):
print(i, tuple1[i])
for i, val in enumerate(tuple1):
print(i, val)
5.4.9 元组的不可变
元组的不可变指的是元组所指向的内存中的内容不可变,但可以重新赋值。
tuple1 = (100, 200, 300)
print(id(tuple1), tuple1)
tuple1 = tuple1 + (1, 2, 3)
print(id(tuple1), tuple1)
如果元组中元素是可变数据类型,其嵌套项可以被修改:
tuple1 = (100, 200, 300, [1, 2, 3])
tuple1[3].append(4)
print(tuple1) # (100, 200, 300, [1, 2, 3, 4])
5.5 集合Set
- 集合是无序的,且不包含重复元素。
- 集合使用
{}定义,数据之间使用,分隔,也可以使用set()定义。 - 集合没有索引,所以不能通过切片方式访问集合元素。
- 集合中元素可以是不同的类型。
- 集合可以进行数学上的集合操作,如并集、交集和差集。
- 集合适用于需要快速成员检查、消除重复项和集合运算的场景。
5.5.1 创建集合
可以通过 {} 或 set() 创建集合,但创建空集合需要使用 set() 而非 {},因为 {} 会创建空字典。
set1 = {1, 2, 3}
set2 = set([1, 2, 3]) # 使用set()函数从列表创建集合
set3 = set()
print(set1, set2, set3)
也可以通过集合推导式创建集合:
set1 = {x for x in range(10) if x % 2 == 0}
print(set1) # {0, 2, 4, 6, 8}
5.5.2 向集合中添加元素
set1 = {1, 2, 3}
set1.add(4)
set1.add(5)
print(set1)
5.5.3 从集合中删除元素
set1 = {1, 2, 3}
set1.remove(2)
print(set1)
5.5.4 检查成员是否为集合中元素
set1 = {1, 2, 3, 4, 5}
print(2 in set1) # True
5.5.5 获取集合长度
set1 = {1, 2, 3, 4, 5}
print(len(set1)) # 5
5.5.6 求集合中元素的最大值、最小值、加和
set1 = {1, 2, 3, 4, 5}
print(max(set1)) # 5
print(min(set1)) # 1
print(sum(set1)) # 15
5.5.7 遍历集合
my_set = {1, 2, 3, 4, 5}
for item in my_set:
print(item)
5.5.8 常用函数
| 函数 | 说明 |
|---|---|
set.add(x) | 添加元素 |
set.update(x) | 添加元素,x 可以为列表、元组、字符串、字典等可迭代对象 |
set.union(x) | 添加元素后返回一个新的集合 |
set.remove(x) | 从集合中移除 x,x 不存在则报错 |
set.discard(x) | 从集合中移除 x,x 不存在也不报错 |
set.pop() | 随机取出集合中的一个元素,集合为空则报错 |
set.clear() | 清空集合 |
set.difference(x1, ...) | 求差集,返回一个新的集合 |
set.difference_update(x1, ...) | 求差集 |
set.intersection(x1, ...) | 求交集,返回一个新的集合 |
set.intersection_update(x1, ...) | 求交集 |
set1 & set2 | 两集合求交集 |
set1 | set2 | 两集合求并集 |
set1 - set2 | 两集合求差集 |
set1.isdisjoint(set2) | 判断两集合是否没有交集 |
set1.issubset(set2) | 判断 set1 是否为 set2 的子集 |
set1.issuperset(set2) | 判断 set2 是否为 set1 的子集 |
set1.symmetric_difference(set2) | 求两集合中不重复的元素,返回新集合 |
set1.symmetric_difference_update(set2) | 求两集合中不重复的元素 |
set.copy() | 拷贝集合 |
len(set) | 返回集合元素个数 |
max(set) | 求集合中元素的最大值 |
min(set) | 求集合中元素的最小值 |
sum(set) | 求集合中元素的加和 |
5.6 字典Dictionary
- 一个无序的键值对集合,键是唯一的,而值可以重复。
- 字典使用
{}定义,键(key)和值(value)使用:连接,每个键值对之间使用,分隔。如{key1: value1, key2: value2}。 - 字典没有索引。
- 字典可以通过键来获取对应的值。
- 值可以取任何数据类型,但键必须是不可变的,如字符串、数字、元组。
5.6.1 创建字典
可以通过 {} 或 dict() 创建字典。
dict1 = {}
dict2 = dict()
dict3 = {"name": "Alice", "age": 18, "gender": "male"}
dict4 = dict(name="Bob", age=20, gender="female")
dict5 = dict([("name", "Tom"), ("age", 22), ("gender", "male")])
也可以通过字典推导式创建字典:
squares = {x: x**2 for x in range(4)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9}
5.6.2 访问字典
可通过 [] 访问字典中的元素。key 不存在时会报错。
dict1 = {"name": "Alice", "age": 18, "gender": "male"}
print(dict1["name"]) # Alice
print(dict1["age"]) # 18
print(dict1["gender"]) # male
print(dict1["address"]) # 报错
也可以通过 get() 获取字典中的元素。key 不存在时会返回 None,也可以指定默认值。
dict1 = {"name": "Alice", "age": 18, "gender": "male"}
print(dict1.get("name")) # Alice
print(dict1.get("address")) # None
print(dict1.get("address", "earth")) # earth
5.6.3 向字典中添加元素
为字典指定的 key 赋值 value,若 key 原本不存在则会被添加。
dict1 = {"name": "Alice", "age": 18, "gender": "male"}
dict1["address"] = "earth"
print(dict1)
5.6.4 修改字典中元素
通过 key 修改对应的 value。
dict1 = {"name": "Alice", "age": 18, "gender": "male"}
dict1["name"] = "Bob"
print(dict1)
5.6.5 检查成员是否为字典中的key
dict1 = {"name": "Alice", "age": 81, "gender": "male"}
print("name" in dict1) # True 检查key是否存在
print("Alice" in dict1) # False 无法直接检查value是否存在
5.6.6 获取字典长度
dict1 = {"name": "Alice", "age": 81, "gender": "male"}
print(len(dict1)) # 3
5.6.7 遍历字典
my_dict = {'Name': 'Tom', 'Age': 17}
# 遍历出所有k
keys = my_dict.keys()
for k in keys:
print(k)
print("-" * 20)
# 遍历出所有v
vals = my_dict.values()
for v in vals:
print(v)
print("-" * 20)
# k-v 遍历
for k in my_dict.keys():
print(k + "---" + str(my_dict[k]))
print("-" * 20)
kv = my_dict.items()
for i in kv:
print(i)
5.6.8 删除字典元素
my_dict = {'Name': 'Tom', 'Age': 17}
del my_dict['Name'] # 删除键 'Name'
# my_dict.clear() # 清空字典
# del my_dict # 删除字典
print(my_dict)
5.6.9 常用函数
| 函数 | 说明 |
|---|---|
del dict[key] | 根据 key 删除键值对 |
dict.pop(key[, default]) | 获取 key 对应的 value,同时删除该键值对 |
dict.popitem() | 取出字典中最后插入的键值对,字典为空则报错 |
dict.clear() | 清空字典 |
dict1.update(dict2) | 将 dict2 中的键值对更新到 dict1 中 |
dict.get(key[, default]) | 获取 key 对应 value,可设置默认值 |
dict.setdefault(key[, default]) | 获取 key 对应 value,若 key 不存在则添加 |
dict.keys() | 获取字典所有的 key,返回视图对象 |
dict.values() | 获取字典所有的 value,返回视图对象 |
dict.items() | 获取字典所有的 (key, value),返回视图对象 |
dict.copy() | 拷贝字典 |
dict.fromkeys(seq[, default]) | 以序列 seq 中元素做字典的 key 创建新字典 |
5.7 列表、元组、字典和集合的区别
| 数据结构 | 是否可变 | 是否重复 | 是否有序 | 定义符号 |
|---|---|---|---|---|
| 列表(List) | 可变 | 允许 | 有序 | [] 或 list() |
| 元组(Tuple) | 不可变 | 允许 | 有序 | () 或 tuple() |
| 字典(Dictionary) | 可变 | 键不允许,值允许 | 键无序(Python 3.7+ 保持插入顺序) | {} 或 dict() |
| 集合(Set) | 可变 | 不允许 | 无序 | {} 或 set() |