考点 6. Python 的组合数据类型

📋 考纲要求

掌握列表、元组、字典、集合等组合数据类型的基本操作。

Python 的组合数据类型(也叫容器类型)是指能一次性存储多个数据元素的类型,这些元素可以是相同/不同类型(如数字、字符串,甚至其他组合类型),核心作用是批量管理和操作一组数据,是 Python 处理多数据场景的基础。

组合数据按存储特性可分为序列、集合和映射 3 个核心类型。

  • (1)序列类型:元素有序,可通过索引访问,支持切片。
  • (2)集合类型:元素无序、唯一,支持集合运算(交/并/差)。
  • (3)映射类型:键值对存储,通过键快速查找值。

一、列表

列表(list)是 Python 中最基础、最常用的可变序列类型,用方括号([])包裹元素,元素之间用逗号分隔,它可以存储任意类型的数据(数字、字符串、布尔值,甚至列表/字典等),且元素有序、可重复、可修改。

1. 列表的基础操作

(1)创建列表

python
# 空列表
empty_list = []
# 包含不同类型元素的列表
mixed_list = [1,"Python",True,3.14,[10,20]]
# 通过 list()函数创建(可将其他可迭代对象转为列表)
from_str = list("hello")    # ['h','e','l','l','o']
from_range = list(range(5))    # [0,1,2,3,4]

(2)访问列表元素(索引与切片)

列表元素有序,可通过索引(从 0 开始)或切片访问,支持正向/反向索引。

  • ①正向索引:list[0](第一个元素)、list[1](第二个元素)……
  • ②反向索引:list[-1](最后一个)、list[-2](倒数第二个)……
  • ③切片:list[起始:结束:步长](左闭右开,步长可选)。
python
nums = [10,20,30,40,50]
# 单个元素
print(nums[0])    # 10(正向索引)
print(nums[-1])    # 50(反向索引)
# 切片
print(nums[1:4])    # [20,30,40](索引 1 到 3)
print(nums[:3])    # [10,20,30](从开头到索引 2)
print(nums[::2])    # [10,30,50](步长 2,隔一个取一个)

(3)修改列表元素

列表是可变类型,可直接通过索引修改元素。

python
fruits = ["苹果","香蕉","橙子"]
fruits[1] = "葡萄"    # 修改第二个元素
print(fruits)    # ['苹果','葡萄','橙子']

2. 列表的常用方法

列表内置了大量方法,可用于增、删、查、改操作,具体见表 8-24 所列。

表 8-24 列表的常用方法

方法作用示例
append(x)在列表末尾添加单个元素 xnums.append(60)→[10,20,30,40,50,60]
extend(iter)批量添加可迭代对象的元素(如列表、字符串)nums.extend([70,80])→[10,20,30,40,50,60,70,80]
insert(index,x)在指定索引位置插入元素 xnums.insert(2,25)→[10,20,25,30,40,50]
remove(x)删除第一个出现的元素 x(元素不存在则报错)nums.remove(30)→[10,20,40,50]
pop([index])删除指定索引的元素(默认删除最后一个),并返回该元素nums.pop(1)→返回 20,列表变为[10,30,40,50]
clear()清空列表nums.clear()→[]
index(x)返回第一个出现的元素 x 的索引(不存在会报错)nums.index(30)→2
count(x)统计元素 x 出现的次数[1,2,2,3,2].count(2)→3
sort([reverse=False])原地排序(默认升序,reverse=True 为降序)[3,1,2].sort()→[1,2,3]
reverse()原地反转列表[1,2,3].reverse()→[3,2,1]
copy()浅拷贝列表(避免修改原列表)new_nums=nums.copy()
python
# 增
nums = [10,20,30]
nums.append(40)    # [10,20,30,40]
nums.extend([50,60])    # [10,20,30,40,50,60]
nums.insert(1,15)    # [10,15,20,30,40,50,60]
# 删
nums.remove(30)    # [10,15,20,40,50,60]
pop_num = nums.pop()    # 删除最后一个元素 60,pop_num=60
nums.clear()    # 清空列表→[]
# 查/统计
fruits = ["苹果","香蕉","苹果","橙子"]
print(fruits.index("苹果"))    # 0
print(fruits.count("苹果"))    # 2
# 排序/反转
scores = [85,92,78,90]
scores.sort()    # 升序→[78,85,90,92]
scores.sort(reverse=True)    # 降序→[92,90,85,78]
scores.reverse()    # 反转→[78,85,90,92]

3. 列表的高级用法

(1)列表推导式

列表推导式是 Python 的特色语法,用一行代码快速生成列表,比循环更高效、简洁。

python
# 基本格式:[表达式 for 变量 in 可迭代对象 if 条件]
# 示例1:生成1~10的平方列表
squares = [x * x for x in range(1,11)]    # [1,4,9,...,100]
# 示例2:筛选偶数
evens = [x for x in range(1,20) if x % 2 == 0]    # [2,4,...,18]

(2)列表的遍历

python
# 遍历元素
fruits = ["苹果","香蕉","橙子"]
for fruit in fruits:
    print(fruit)

(3)列表的拼接与重复

python
a = [1,2,3]
b = [4,5,6]
# 拼接
c = a + b    # [1,2,3,4,5,6]
# 重复
d = a * 3    # [1,2,3,1,2,3,1,2,3]

二、元组

元组(tuple)是 Python 中不可变的有序序列类型,用圆括号()包裹元素(也可省略括号),元素之间用逗号分隔。它可以存储任意类型的数据(数字、字符串、列表、字典等),元素有序、可重复,但创建后无法修改元素本身(不可变是元组的核心特征)。

1. 元组的基础操作

(1)创建元组

元组的创建有多种方式,重点注意单元素元组的特殊写法(必须加逗号)。

python
# 空元组
empty_tuple = ()
# 多元素元组(标准写法)
num_tuple = (10,20,30,40)
# 多元素元组(省略括号:Python 仍识别为元组)
fruit_tuple = "苹果","香蕉","橙子"
# 单元素元组(必须加逗号!否则只是普通变量)
single_tuple = (50,)    # 正确的单元素元组
wrong_single = (50)    # 本质是整数 50,不是元组
print(type(single_tuple))    # <class 'tuple'>
print(type(wrong_single))    # <class 'int'>
# 通过 tuple()函数创建(转换其他可迭代对象)
from_list = tuple([1,2,3])    # (1,2,3)
from_str = tuple("hello")    # ('h','e','l','l','o')

(2)访问元组元素(索引与切片)

元组和列表一样支持正向/反向索引和切片,二者语法完全一致(因为都是序列类型)。

python
t = (100,200,300,400,500)
# 单个元素访问
print(t[0])    # 100(正向索引,第一个元素)
print(t[-1])    # 500(反向索引,最后一个元素)
# 切片(左闭右开,步长可选)
print(t[1:4])    # (200,300,400)(索引 1 到 3)
print(t[::2])    # (100,300,500)(步长 2)
print(t[::-1])    # (500,400,300,200,100)(反转元组)

(3)元组的"修改"(伪修改)

元组本身不可变(无法直接修改、添加、删除元素),但如果元组中包含可变元素(如列表),那么可变元素的内部可以修改。

python
# 错误示例:直接修改元组元素(报错)
t1 = (1,2,3)
# t1[0] = 100    # TypeError:'tuple' object does not support item assignment
# 合法示例:修改元组中的可变元素(列表)
t2 = (1,[2,3],4)
t2[1][0] = 200    # 修改元组内列表的元素
print(t2)    # (1,[200,3],4)
# 间接"修改"元组:拼接生成新元组
t3 = (10,20)
t4 = t3 + (30,40)    # 生成新元组,原元组 t3 不变
print(t3)    # (10,20)
print(t4)    # (10,20,30,40)

2. 元组的内置方法

由于元组不可变,它的内置方法远少于列表,只有 2 个核心的内置方法,见表 8-25 所列。

表 8-25 元组的内置方法

方法作用示例
index(x)返回第一个出现的元素 x 的索引,元素不存在则报错(1,2,3,2).index(2)→1
count(x)统计元素 x 在元组中出现的次数(1,2,2,3,2).count(2)→3
python
t = ("苹果","香蕉","苹果","橙子","香蕉")
# 查找元素索引
print(t.index("香蕉"))    # 1
# 统计元素次数
print(t.count("苹果"))    # 2

3. 元组其他常用操作

(1)元组的遍历

和列表完全一致,支持直接遍历元素或遍历索引+元素。

python
t = ("周一","周二","周三")
# 遍历元素
for day in t:
    print(day)
# 遍历索引+元素(用 enumerate)
for idx,day in enumerate(t):
    print(f"索引{idx}:{day}")    # 索引 0:周一,索引 1:周二...

(2)元组解包

元组解包是 Python 的便捷语法,可将元组的元素一次性赋值给多个变量,是元组最常用的场景之一。

python
# 基础解包
t = (18,"小明","男")
age,name,gender = t    # 解包赋值
print(age)    # 18
print(name)    # 小明
# 扩展解包(*接收多个元素)
t2 = (1,2,3,4,5)
a,*b,c = t2    # a=1,c=5,b 接收中间所有元素
print(a)    # 1
print(b)    # [2,3,4](注意:*接收的结果是列表)
print(c)    # 5
# 函数返回多值(本质是元组解包)
def get_info():
    return "小红",20,"女"    # 省略括号的元组
name,age,gender = get_info()    # 解包函数返回的元组
print(f"姓名:{name},年龄:{age}")

(3)元组的拼接与重复

和列表语法一致,操作后生成新元组。

python
t1 = (1,2)
t2 = (3,4)
# 拼接
t3 = t1 + t2    # (1,2,3,4)
# 重复
t4 = t1 * 3    # (1,2,1,2,1,2)

三、字典

字典(dict)是 Python 中唯一的映射类型,以"键值(key-value)"对的形式存储数据,用大括号({})包裹,键和值之间用冒号(:)分隔,键值对之间用逗号(,)分隔,有以下 4 个核心特征。

  • (1)键(key):唯一,不可变(只能是字符串、数字、元组等不可变类型,列表/字典等可变类型不能作为键)。
  • (2)值(value):可以是任意类型(数字、字符串、列表、字典等),可重复。
  • (3)有序性:Python 3.7+版本中,字典默认保留键值对的插入顺序(3.6 及以下为无序)。
  • (4)可变性:可随时增、删、改键值对。

1. 字典的基础操作

(1)创建字典

字典有多种创建方式,优先掌握以下示例的前 3 种。

python
# 空字典
empty_dict = {}
# 标准创建(键值对形式)
user = {"name":"小明","age":18,"gender":"男"}
# 用 dict()函数创建(关键字参数)
user2 = dict(name="小红",age=20,gender="女")
# 从键值对列表创建(双值子序列)
kv_list = [("math",90),("chinese",85)]
scores = dict(kv_list)    # {'math':90,'chinese':85}
# 字典推导式(高效创建,后续讲解)
num_dict = {x: x*2 for x in range(1,4)}    # {1:2,2:4,3:6}

(2)访问字典的值

核心方式是通过键访问,也可通过 get()方法访问。

python
user = {"name":"小明","age":18}
# 方法1:直接通过键访问(键不存在会报错)
print(user["name"])    # 小明
# print(user["height"])    # KeyError:'height'
# 方法2:get()方法(键不存在返回 None 或指定默认值,推荐)
print(user.get("age"))    # 18
print(user.get("height"))    # None(不报错)
print(user.get("height",175))    # 175(键不存在时返回默认值)

(3)修改/添加键值对

字典的可变性主要体现在修改值、添加新键值对上,语法统一为"字典[键]=值"。

python
user = {"name":"小明","age":18}
# 修改已有键的值
user["age"] = 19
print(user)    # {'name':'小明','age':19}
# 添加新的键值对(键不存在则自动新增)
user["height"] = 175
user["scores"] = [90,85,95]
print(user)    # {'name':'小明','age':19,'height':175,'scores':[90,85,95]}

(4)删除键值对

常用的有 3 种方式,每种方式都有自己适用的场景。

python
user = {"name":"小明","age":18,"height":175}
# 方法1:del 语句(删除指定键值对,键不存在报错)
del user["height"]
print(user)    # {'name':'小明','age':18}
# 方法2:pop()方法(删除并返回指定键的值,键不存在可指定默认值)
age = user.pop("age")
print(age)    # 18(返回被删除的值)
print(user)    # {'name':'小明'}
# 键不存在时指定默认值,避免报错
height = user.pop("height",0)
# 方法3:clear()方法(清空所有键值对,保留字典对象)
user.clear()
print(user)    # {}

2. 字典的常用方法

字典内置了丰富的方法,其中高频使用的核心方法见表 8-26 所列。

表 8-26 字典的常用方法

方法作用示例
keys()返回所有键的可迭代对象(dict_keys),可转列表user.keys()→dict_keys(['name','age'])
values()返回所有值的可迭代对象(dict_values)user.values()→dict_values(['小明',18])
items()返回所有键值对的可迭代对象(dict_items),每个元素是(键,值)元组user.items()→dict_items([('name','小明'),('age',18)])
get(key,default=None)访问键的值,不存在返回 defaultuser.get('height',175)→175
pop(key,default)删除并返回指定键的值,不存在则返回 defaultuser.pop('age')→18
popitem()删除并返回最后插入的键值对(3.7+),空字典报错user.popitem()→('age',18)
update(dict)批量添加/修改键值对(覆盖已有键)user.update({'age':19,'gender':'男'})
clear()清空字典user.clear()→{}
copy()浅拷贝字典new_user = user.copy()
python
user = {"name":"小明","age":18,"gender":"男"}
# 1. 获取所有键、值、键值对
print("所有键:",list(user.keys()))    # ['name','age','gender']
print("所有值:",list(user.values()))    # ['小明',18,'男']
print("所有键值对:",list(user.items()))    # [('name','小明'),('age',18),('gender','男')]
# 2. 批量更新
user.update({"age":19,"height":175})
print("更新后:",user)    # {'name':'小明','age':19,'gender':'男','height':175}
# 3. 删除最后插入的键值对
last_item = user.popitem()
print("删除的键值对:",last_item)    # ('height',175)
print("删除后:",user)    # {'name':'小明','age':19,'gender':'男'}

3. 字典的高级用法

(1)字典的遍历

字典遍历的核心是遍历键、值、键值对,其中遍历键值对最常用。

python
user = {"name":"小明","age":18,"gender":"男"}
# 方法1:遍历键(默认遍历键)
for key in user:
    print(f"键:{key},值:{user[key]}")
# 方法2:遍历键值对
for key,value in user.items():
    print(f"{key}:{value}")
# 方法3:只遍历值
for value in user.values():
    print("值:",value)

(2)字典的嵌套

字典的值可以是任意类型,当值为字典、列表类型时,就是嵌套字典,常用于存储复杂的结构化数据。

python
# 嵌套字典:存储学生信息(包含成绩字典)
students = {
    "小明": {
        "age":18,
        "gender":"男",
        "scores":{"math":90,"chinese":85}
    },
    "小红": {
        "age":17,
        "gender":"女",
        "scores":{"math":95,"chinese":92}
    }
}
# 访问嵌套字典的值
print(students["小明"]["scores"]["math"])    # 90
# 修改嵌套字典的值
students["小红"]["age"] = 18
# 新增嵌套键值对
students["小明"]["scores"]["english"] = 88
print(students["小明"])
# {'age':18,'gender':'男','scores':{'math':90,'chinese':85,'english':88}}

四、集合

集合(set)是 Python 中无序、不重复的可变容器类型,用大括号({})包裹元素,元素之间用逗号分隔,有以下 3 个核心特征。

  • (1)无序性:元素没有固定顺序,无法通过索引访问(这是与列表/元组最核心的区别)。
  • (2)唯一性:自动去重,集合中不会出现重复元素。
  • (3)可变性:可添加、删除元素,但集合中的元素必须是不可变类型(如数字、字符串、元组,列表/字典等可变类型不能作为集合元素)。

1. 集合的基础操作

(1)创建集合

重点注意空集合和单元素集合的创建方式,以及集合的自动去重特性。

python
# 空集合(必须用 set(),{}是空字典)
empty_set = set()
print(type(empty_set))    # <class 'set'>
print(type({}))    # <class 'dict'>
# 普通集合(自动去重)
num_set = {1,2,2,3,3,3}    # 重复元素会被自动去除
print(num_set)    # {1,2,3}
# 混合类型集合(元素为不可变类型)
mix_set = {1,"python",(10,20)}    # 合法
# 错误示例:包含可变元素(列表)会报错
# wrong_set = {1,[2,3]}    # TypeError:unhashable type:'list'
# 通过 set()函数创建(转换其他可迭代对象)
from_list = set([1,2,2,3])    # {1,2,3}
from_str = set("hello")    # {'h','e','l','o'}(自动去重 l)
from_range = set(range(5))    # {0,1,2,3,4}

(2)访问集合元素

集合无序,无法通过索引/切片访问,只能通过成员判断(in/not in)检查元素是否存在。

python
s = {10,20,30,40}
# 判断元素是否存在(核心访问方式)
print(20 in s)    # True
print(50 not in s)    # True
# 遍历集合元素(顺序不固定)
for num in s:
    print(num)    # 输出顺序可能是 10,30,20,40(随机)

(3)添加元素

集合提供两种添加元素的方法,分别适用于添加单个元素和批量添加元素。

python
s = {1,2,3}
# 方法 1:add() —— 添加单个元素(元素已存在则无操作)
s.add(4)
s.add(2)      # 元素 2 已存在,无变化
print(s)      # {1,2,3,4}
# 方法 2:update() —— 批量添加可迭代对象的元素(如列表、字符串、集合)
s.update([5,6])        # 添加列表元素
s.update("ab",(7,8)) # 同时添加字符串和集合元素
print(s)  # {1,2,3,4,5,6,7,8,'a','b'}

(4)删除元素

集合有 4 种删除元素的方法,每种方法都有自己适用的场景。

python
s = {1,2,3,4,5}
# 方法 1:remove(x) —— 删除指定元素,元素不存在则报错
s.remove(3)
# s.remove(10)   # KeyError:10
# 方法 2:discard(x) —— 删除指定元素,元素不存在则无操作(推荐,更安全)
s.discard(4)
s.discard(10)     # 无错误,集合不变
print(s)  # {1,2,5}
# 方法 3:pop() —— 随机删除并返回一个元素(集合无序,无法指定)
pop_num = s.pop()
print("删除的元素:",pop_num)   # 可能是 1/2/5
print("删除后:",s)
# 方法 4:clear() —— 清空集合
s.clear()
print(s)  # set()

2. 集合的核心:集合运算

集合最强大的功能是支持数学中的集合运算(交集、并集、差集、对称差集),既可以用运算符,也可以用对应的方法,具体见表 8-27 所列。

表 8-27 集合的运算方法

运算类型运算符方 法含 义示 例<br>(s1 = {1,2,3},s2 = {2,3,4})
并集\union()两个集合所有不重复的元素
交集&intersection()两个集合共同的元素s1 & s2 → {2,3}
差集–difference()属于 s1 但不属于 s2 的元素s1 - s2 → {1}
对称差集^symmetric_difference()两个集合中互不相同的元素s1 ^ s2 → {1,4}

(1)基础用法

python
s1 = {1,2,3,4}
s2 = {3,4,5,6}
# 并集(合并所有元素,去重)
print("并集:",s1 | s2)               # {1,2,3,4,5,6}
print("并集(方法):",s1.union(s2))   # 同上
# 交集(共同元素)
print("交集:",s1 & s2)                # {3,4}
print("交集(方法):",s1.intersection(s2))  # 同上
# 差集(s1 有,s2 没有)
print("差集(s1-s2):",s1 - s2)        # {1,2}
print("差集(方法):",s1.difference(s2))  # 同上
# 对称差集(互不相同的元素)
print("对称差集:",s1 ^ s2)             # {1,2,5,6}
print("对称差集(方法):",s1.symmetric_difference(s2))   # 同上

(2)集合关系的判断

判断两个集合的包含关系,如子集、超集、不相交。

python
s1 = {1,2}
s2 = {1,2,3}
s3 = {4,5}
# 子集:s1 是否全部包含在 s2 中
print(s1.issubset(s2))    # True
print(s1 <= s2)          # True(运算符写法)
# 超集:s2 是否包含 s1 的所有元素
print(s2.issuperset(s1))  # True
print(s2 >= s1)  # True(运算符写法)