目录
[2.1 列表 list(可变序列)](#2.1 列表 list(可变序列))
[2.2 元组 tuple(不可变序列)](#2.2 元组 tuple(不可变序列))
[3.1 索引取值](#3.1 索引取值)
[3.2 切片截取子序列](#3.2 切片截取子序列)
[3.3 通用内置函数](#3.3 通用内置函数)
[3.4 拼接 +、重复复制 *](#3.4 拼接 +、重复复制 *)
[3.5 成员判断 in / not in](#3.5 成员判断 in / not in)
[3.6 序列布尔判定规则](#3.6 序列布尔判定规则)
[3.7 序列解包(多变量赋值)](#3.7 序列解包(多变量赋值))
[4.1 新增元素](#4.1 新增元素)
[4.2 修改元素](#4.2 修改元素)
[4.3 查询统计](#4.3 查询统计)
[4.4 删除元素](#4.4 删除元素)
[4.5 列表排序 sort()](#4.5 列表排序 sort())
[自定义排序 key 参数(核心实战)](#自定义排序 key 参数(核心实战))
[内置函数 sorted():返回新列表的通用排序](#内置函数 sorted():返回新列表的通用排序)
上一章我们完整学习了函数的定义、参数传递、返回值与全局/局部变量作用域,学会了把重复代码封装复用。本章将正式进入组合数据类型 板块,先讲解三大序列:字符串、列表 list 、元组 tuple ,统一梳理序列的通用特性,重点区分可变列表 与不可变元组,并配套电影排序实战案例,帮助大家在实际场景中灵活运用。
一、Python数据类型整体分类
Python 数据分为两大类,本章聚焦序列类型。先回顾整体分类,便于建立清晰的知识框架:
- 基础单一数据类型:
int、float、complex、bool、str字符串 - 组合数据类型(批量存储多元素)
- 序列类型:有序、支持索引切片,
str、list列表、tuple元组 - 映射类型:无序键值对,
dict字典 - 集合类型:无序、元素唯一,
set集合
- 序列类型:有序、支持索引切片,
序列的核心定义是有序排列的一组元素 。每个元素都拥有独立的正向/反向索引 ,支持切片 、长度计算 、拼接 、重复复制等通用操作。理解序列的共性,是掌握列表和元组的基础。
二、列表与元组基础定义
2.1 列表 list(可变序列)
列表使用方括号 [] 定义,内部可存放任意类型的数据(数字、字符串、布尔、复数、嵌套列表/元组等),创建后支持增、删、改操作,是日常开发中使用最频繁的数据结构之一。
python
# 混合类型列表
box = [546, 7.8, "hello", True, 1+2j, "run"]
# 空列表两种创建方式
ls1 = []
ls2 = list()
# 将字符串转为列表
ls3 = list("abc")
print(ls3) # ['a', 'b', 'c']
2.2 元组 tuple(不可变序列)
元组使用圆括号 () 定义,同样支持混合数据存储,但创建完成后不能修改、新增、删除元素 ,适合存放固定不变的数据。
这里有一个重点易错规则:单元素元组末尾必须加逗号 , ,否则 Python 会把它当作普通数值处理。
需要特别说明的是:元组的"不可变"仅限制自身元素的引用地址 ,即不能增删改元组内的元素个数或替换某个元素指向的对象;但如果元组内部存放的是可变容器(如列表、字典、集合),这些容器内部的元素仍然可以自由修改。
python
t1 = (3,) # 正确:单元素元组
t2 = (3) # 错误:仅代表数字3,不是元组
多元素元组
box = (546, 7.8, "hello", True, 1+2j, "run")
列表与元组核心区别汇总
| 类型 | 标识 | 是否可变 | 支持操作 | 适用场景 |
|---|---|---|---|---|
| list列表 | [] |
可变 | 增删改查、排序 | 频繁修改数据、临时存储批量内容 |
| tuple元组 | () |
不可变 | 仅查询、切片、拼接 | 固定不变的数据,保证数据安全 |
三、序列通用基础操作
字符串、列表、元组共享一套基础语法,索引、切片、长度、拼接、重复、成员判断完全通用。
3.1 索引取值
正向索引从 0 开始,反向索引从 -1 开始,格式:序列[下标]
python
box = [546, 7.8, "hello", True, 1+2j, "run"]
print(box[3]) # True 正向索引
print(box[-2]) # (1+2j) 反向索引
上面的示例演示了如何通过索引从列表中取值。box[3] 使用正向索引 ,从 0 开始计数,因此下标 3 对应第 4 个元素 True;box[-2] 使用反向索引 ,从 -1 开始计数,-1 表示最后一个元素,所以 -2 表示倒数第 2 个元素 (1+2j)。正向索引适合从头按顺序取元素,反向索引则适合从尾部快速定位元素,两者结合可以灵活访问序列中的任意位置。
3.2 切片截取子序列
语法:序列[起始:结束:步长],遵循左闭右开原则,省略参数自动取边界
python
box = (546, 7.8, "hello", True, 1+2j, "run")
print(box[1:4]) # (7.8, 'hello', True)
print(box[:-2]) # 从头截取到倒数第二个之前
print(box[::-1]) # 整体倒序
切片用于截取序列的子序列,语法为 序列[起始:结束:步长],遵循左闭右开 原则,即包含起始下标、不包含结束下标。box[1:4] 截取下标 1 到 3 的元素,得到 (7.8, 'hello', True);box[:-2] 省略起始下标表示从头开始,截取到倒数第 2 个元素之前;box[::-1] 使用步长 -1 实现整体倒序 。切片返回的是一个新的子序列,原序列保持不变,因此可以安全地用于元组和字符串。
3.3 通用内置函数
python
box = [8,3,7,2,1,9]
print(len(box)) # len() 获取元素总数
print(max(box)) # max() 最大值
print(min(box)) # min() 最小值
这三个内置函数对所有序列通用。len(box) 返回序列的元素总数,常用于循环次数控制或判断序列是否为空;max(box) 返回序列中的最大值,min(box) 返回最小值,二者要求序列内元素类型可比较。需要注意的是,max() 和 min() 对字符串序列按字符编码比较,对混合类型序列(如同时包含数字和字符串)会报错,使用时需保证元素类型一致。
3.4 拼接 +、重复复制 *
python
# 拼接
t = (1,2)
t += (3,4)
print(t) # (1, 2, 3, 4)
ls = [1,2]
ls += [3,4]
print(ls) # [1, 2, 3, 4]
重复复制
print([1,2]*2) # [1, 2, 1, 2]
print((1,2)*2) # (1, 2, 1, 2)
拼接运算符 + 用于把两个序列合并成一个新序列,t += (3,4) 等价于 t = t + (3,4),会生成一个新元组并重新赋值给 t;重复复制运算符 * 用于把序列重复指定次数,[1,2]*2 得到 [1, 2, 1, 2]。这两个操作对字符串、列表、元组都通用,且都返回新序列,原序列保持不变。
3.5 成员判断 in / not in
判断元素是否存在于序列,返回布尔值 True/False
python
print("八佰" in ["战狼Ⅱ","八佰"]) # True
print(6.8 not in [1,2,3]) # True
成员判断运算符 in 和 not in 用于检查某个元素是否存在于序列中,返回布尔值 True 或 False。"八佰" in ["战狼Ⅱ","八佰"] 判断字符串 "八佰" 是否在列表中,结果为 True;6.8 not in [1,2,3] 判断 6.8 是否不在列表中,结果为 True。该操作常用于条件判断,例如在删除元素前先确认元素是否存在,避免程序报错。
3.6 序列布尔判定规则
和之前分支判断规则统一:
- 空列表
[]、空元组()→False - 非空列表、非空元组 →
True
可搭配while循环遍历删除元素:
python
t = ['1','2','3']
while t:
print(t[-1])
t = t[:-1]
3.7 序列解包(多变量赋值)
序列解包 是开发中高频使用 的基础语法,可以一次性把列表或元组中的元素按顺序赋值给多个变量,让代码更简洁、可读性更强。
python
# 列表解包
a, b, c = [1, 2, 3]
print(a, b, c) # 1 2 3
元组解包
x, y = (10, 20)
print(x, y) # 10 20
左侧变量的个数必须与右侧序列的元素个数完全一致 ,否则会抛出 ValueError 异常。解包同样适用于字符串,例如 a, b, c = "abc" 会把三个字符分别赋给 a、b、c。
进阶用法: 使用星号 * 收集多余元素,实现"部分解包":
python
# 星号收集剩余元素,返回列表
first, *rest = [1, 2, 3, 4]
print(first) # 1
print(rest) # [2, 3, 4]
常用于交换两个变量的值
m, n = 3, 5
m, n = n, m
print(m, n) # 5 3
一句话记忆: 序列解包让"多变量同时赋值"一步到位,配合星号 * 还能灵活收集剩余元素,是简化代码的实用技巧。
四、列表专属操作(增、删、改、查、排序)
元组不可变,无增删改方法,只有列表支持以下操作。
4.1 新增元素
append(元素):末尾追加单个元素
python
ls = ["战狼Ⅱ"]
ls.append("我和我的祖国")
print(ls) # ['战狼Ⅱ', '我和我的祖国']
insert(下标,元素):指定位置插入
python
ls.insert(1, "红海行动")
print(ls) # ['战狼Ⅱ', '红海行动', '我和我的祖国']
extend(序列):批量追加另一组序列所有元素
python
lt = ["八佰"]
ls.extend(lt)
print(ls) # ['战狼Ⅱ', '红海行动', '我和我的祖国', '八佰']
append() 与 extend() 核心区别(极易混淆):
| 对比项 | append(元素) | extend(序列) |
|---|---|---|
| 作用 | 把传入参数整体当成一个元素添加到末尾 | 把传入序列拆开,逐个追加内部元素 |
| 传入列表时 | 整个列表作为一个嵌套元素加入 | 列表内每个元素分别追加 |
| 列表长度变化 | 长度 +1 | 长度 + 传入序列的元素个数 |
对比示例:
python
ls = ["战狼Ⅱ", "八佰"]
append:把整个列表当成一个元素
ls.append(["红海行动", "我和我的祖国"])
print(ls)
['战狼Ⅱ', '八佰', ['红海行动', '我和我的祖国']] 长度 +1
extend:拆开序列,逐个追加
ls = ["战狼Ⅱ", "八佰"]
ls.extend(["红海行动", "我和我的祖国"])
print(ls)
['战狼Ⅱ', '八佰', '红海行动', '我和我的祖国'] 长度 +2
一句话记忆: append 是把参数整个装进 列表,extend 是把序列拆开铺平再逐个放入。
4.2 修改元素
通过索引/切片直接覆盖赋值
python
ls = ["战狼Ⅱ","红海行动","八佰"]
# 单元素修改
ls[1] = "我和我的祖国"
# 切片批量修改
ls[1:] = ["红海行动"]
4.3 查询统计
.count(元素):统计元素出现次数.index(元素):返回元素第一次出现的索引下标
python
ls = ["战狼Ⅱ","八佰","战狼Ⅱ"]
print(ls.count("战狼Ⅱ")) # 2
print(ls.index("战狼Ⅱ")) # 0
4.4 删除元素
del:按下标/切片删除
python
ls = ["战狼Ⅱ","红海行动","八佰"]
del ls[1] # 删除下标1元素
del ls[1:] # 删除下标1及之后全部
.remove(元素):按内容删除第一个匹配项
python
ls.remove("红海行动")
.pop(下标):取出并删除指定下标元素,不传参数默认删末尾
python
ls.pop(1)
.clear():清空整个列表,变为空列表
python
ls.clear()
4.5 列表排序 sort()
基础升序/降序
python
ls = [8,3,7,2,1,9]
ls.sort() # 默认升序从小到大
print(ls) # [1, 2, 3, 7, 8, 9]
ls.sort(reverse=True) # reverse=True 降序从大到小
print(ls) # [9, 8, 7, 3, 2, 1]
自定义排序 key 参数(核心实战)
sort(key=函数),按函数返回值排序,支持普通函数与lambda匿名函数。
实战任务1:电影列表按名称长度排序
python
# 原始电影列表
ls = ["战狼Ⅱ","红海行动","八佰","我和我的祖国"]
# 写法1:自定义函数
def get_len(x):
return len(x)
ls.sort(key=get_len)
写法2:lambda匿名函数(简洁推荐)
ls.sort(key=lambda x: len(x))
print(ls)
输出:['八佰', '战狼Ⅱ', '红海行动', '我和我的祖国']
实战任务2:嵌套元组,按电影豆瓣评分排序
python
# (电影名, 评分)
movie_list = [("战狼Ⅱ",7.1),("红海行动",8.3),("八佰",8.1),("我和我的祖国",7.8)]
# 按元组第二个元素(评分)升序
movie_list.sort(key=lambda x: x[-1])
print(movie_list)
# [('战狼Ⅱ', 7.1), ('我和我的祖国', 7.8), ('八佰', 8.1), ('红海行动', 8.3)]
内置函数 sorted():返回新列表的通用排序
与 sort() 原地修改 列表不同,内置函数 sorted() 会返回一个新的排序列表 ,原序列保持不变。它适用于所有可迭代序列 ,包括字符串、元组和列表,是处理不可变序列排序的唯一选择。
python
# 对列表排序:返回新列表,原列表不变
ls = [8, 3, 7, 2, 1, 9]
new_ls = sorted(ls)
print(new_ls) # [1, 2, 3, 7, 8, 9]
print(ls) # [8, 3, 7, 2, 1, 9] 原列表未被修改
对元组排序:返回新列表
t = (8, 3, 7)
print(sorted(t)) # [3, 7, 8]
对字符串排序:按字符编码升序,返回字符列表
s = "cba"
print(sorted(s)) # ['a', 'b', 'c']
降序排序
print(sorted(ls, reverse=True)) # [9, 8, 7, 3, 2, 1]
搭配 key 参数:按电影名称长度排序
movie_list = ["战狼Ⅱ", "红海行动", "八佰", "我和我的祖国"]
print(sorted(movie_list, key=lambda x: len(x)))
['八佰', '战狼Ⅱ', '红海行动', '我和我的祖国']
sort() 与 sorted() 核心区别:
| 对比项 | sort() | sorted() |
|---|---|---|
| 适用对象 | 仅列表 | 列表、元组、字符串等所有可迭代序列 |
| 是否修改原序列 | 原地修改原列表 | 不修改原序列,返回新列表 |
| 返回值 | None(无返回值) | 新的排序列表 |
| key / reverse 参数 | 支持 | 支持 |
一句话记忆: list.sort() 仅列表可用,原地修改 、无返回值;sorted(序列) 字符串 / 元组 / 列表全部通用,返回新列表、不改变原数据。
五、列表推导式
快速批量生成列表,简化循环创建列表代码,格式:
[表达式 for 变量 in 序列 if 条件]
python
# 生成 0,2,4
L = [i*2 for i in range(3)]
print(L) # [0, 2, 4]
筛选1~10偶数
even = [x for x in range(1,11) if x%2 == 0]
print(even)
六、序列遍历循环
所有序列都可直接放入 for 循环遍历,无需额外 range:
python
# 遍历字符串
for c in "你好!":
print(c)
# 遍历列表
for name in ["战狼Ⅱ","八佰"]:
print(name)
除了直接遍历元素,开发中还经常需要同时获取元素的索引和值 。此时可以使用内置函数 enumerate(),它会在遍历时自动为每个元素生成一个序号(默认从 0 开始) ,返回 (索引, 元素) 的配对,配合序列解包即可一步拿到下标和内容:
python
# 同时获取索引和元素
names = ["战狼Ⅱ", "红海行动", "八佰"]
for idx, name in enumerate(names):
print(idx, name)
# 输出:
# 0 战狼Ⅱ
# 1 红海行动
# 2 八佰
enumerate(names) 会依次产出 (0, "战狼Ⅱ")、(1, "红海行动")、(2, "八佰") 这样的配对,再用 for idx, name in ... 解包,就能在循环体内同时使用下标 idx 和元素 name。相比手动维护一个计数器变量,enumerate() 更简洁、不易出错。
实际开发应用场景: 当需要给数据带上序号输出时非常实用,例如打印带编号的排行榜、为列表项生成序号、在遍历时定位并修改指定位置的元素等。还可以通过 start 参数指定起始序号,让编号从 1 开始,更符合日常习惯:
python
# 从 1 开始编号,输出电影排行榜
movies = ["战狼Ⅱ", "红海行动", "八佰"]
for rank, movie in enumerate(movies, start=1):
print(f"第{rank}名:{movie}")
# 输出:
# 第1名:战狼Ⅱ
# 第2名:红海行动
# 第3名:八佰
一句话记忆: 需要"带序号遍历"时就用 enumerate(序列, start=起始值),配合解包同时拿到索引和元素,是处理带序号数据的首选写法。
七、本章核心易错点总结
- 元组单元素必须加逗号
(3,),否则会被识别为数字; - 元组不可变 ,无法使用
append、sort、del等修改操作; - sort() 仅列表可用 ,直接修改原列表;字符串、元组无
sort方法;
下面用一张对比表格,把最容易出错的三个点拆开来看:
| 易错点描述 | 错误代码示例 | 正确代码示例 | 原因解析 |
|---|---|---|---|
| 单元素元组忘记加逗号 | t = (3) |
t = (3,) |
圆括号在 Python 中同时用于表达式分组,(3) 会被解析为普通整数 3,而不是元组;只有末尾加上逗号,Python 才会把它识别为单元素元组。 |
| 对元组执行修改操作 | t = (1, 2, 3) t.append(4) |
t = (1, 2, 3) t = t + (4,) |
元组是不可变序列,创建后不能增、删、改元素,调用 append、sort、del 等方法会直接报错;需要变更时只能通过拼接等方式生成新元组。 |
| 对字符串或元组调用 sort() | s = "cba" s.sort() |
s = "cba" ls = sorted(s) |
sort() 是列表专属方法,会原地修改原列表;字符串和元组不可变,没有 sort 方法。若想对它们排序,应使用内置函数 sorted(),它会返回一个新的排序列表。 |
- sort(key=lambda)自定义排序是考试、项目高频考点;
- 空序列判定为False,可直接用于while循环条件;
- 切片左闭右开,结束下标对应的元素不会被截取。
八、本章总结
- 组合数据分为序列、映射、集合三类,序列有序、支持索引切片;
- 列表
[]可变 ,支持完整增删改查;元组()不可变,仅用于读取存储; - 字符串、列表、元组共享索引、切片、len、+、*、in通用操作;
- 列表sort搭配key/lambda实现自定义排序,可完成文本、多维数据排序;
- 列表推导式快速批量生成数据,简化循环代码;
- 序列解包 可一次性把多个元素按顺序赋给多个变量,配合星号
*还能收集剩余元素,是简化多变量赋值的高频技巧; - **enumerate(序列, start=起始值)**在遍历时同时返回索引和元素,配合解包即可一步拿到下标与内容,是处理带序号数据的首选写法。