Python 组合数据类型——序列(列表 & 元组)

目录

一、Python数据类型整体分类

二、列表与元组基础定义

[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 参数(核心实战))

实战任务1:电影列表按名称长度排序

实战任务2:嵌套元组,按电影豆瓣评分排序

[内置函数 sorted():返回新列表的通用排序](#内置函数 sorted():返回新列表的通用排序)

五、列表推导式

六、序列遍历循环

七、本章核心易错点总结

八、本章总结


上一章我们完整学习了函数的定义、参数传递、返回值与全局/局部变量作用域,学会了把重复代码封装复用。本章将正式进入组合数据类型 板块,先讲解三大序列:字符串、列表 list元组 tuple ,统一梳理序列的通用特性,重点区分可变列表不可变元组,并配套电影排序实战案例,帮助大家在实际场景中灵活运用。

一、Python数据类型整体分类

Python 数据分为两大类,本章聚焦序列类型。先回顾整体分类,便于建立清晰的知识框架:

  1. 基础单一数据类型:intfloatcomplexboolstr 字符串
  2. 组合数据类型(批量存储多元素)
    • 序列类型:有序、支持索引切片,strlist 列表、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 个元素 Truebox[-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

成员判断运算符 innot in 用于检查某个元素是否存在于序列中,返回布尔值 TrueFalse"八佰" in ["战狼Ⅱ","八佰"] 判断字符串 "八佰" 是否在列表中,结果为 True6.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" 会把三个字符分别赋给 abc

进阶用法: 使用星号 * 收集多余元素,实现"部分解包":

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 新增元素

  1. append(元素):末尾追加单个元素
python 复制代码
ls = ["战狼Ⅱ"]
ls.append("我和我的祖国")
print(ls) # ['战狼Ⅱ', '我和我的祖国']
  1. insert(下标,元素):指定位置插入
python 复制代码
ls.insert(1, "红海行动")
print(ls) # ['战狼Ⅱ', '红海行动', '我和我的祖国']
  1. 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 查询统计

  1. .count(元素):统计元素出现次数
  2. .index(元素):返回元素第一次出现的索引下标
python 复制代码
ls = ["战狼Ⅱ","八佰","战狼Ⅱ"]
print(ls.count("战狼Ⅱ")) # 2
print(ls.index("战狼Ⅱ")) # 0

4.4 删除元素

  1. del:按下标/切片删除
python 复制代码
ls = ["战狼Ⅱ","红海行动","八佰"]
del ls[1]    # 删除下标1元素
del ls[1:]   # 删除下标1及之后全部
  1. .remove(元素):按内容删除第一个匹配项
python 复制代码
ls.remove("红海行动")
  1. .pop(下标):取出并删除指定下标元素,不传参数默认删末尾
python 复制代码
ls.pop(1)
  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=起始值),配合解包同时拿到索引和元素,是处理带序号数据的首选写法。

七、本章核心易错点总结

  1. 元组单元素必须加逗号 (3,),否则会被识别为数字;
  2. 元组不可变 ,无法使用 appendsortdel 等修改操作;
  3. 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(),它会返回一个新的排序列表。
  1. sort(key=lambda)自定义排序是考试、项目高频考点;
  2. 空序列判定为False,可直接用于while循环条件;
  3. 切片左闭右开,结束下标对应的元素不会被截取。

八、本章总结

  1. 组合数据分为序列、映射、集合三类,序列有序、支持索引切片;
  2. 列表[]可变 ,支持完整增删改查;元组()不可变,仅用于读取存储;
  3. 字符串、列表、元组共享索引、切片、len、+、*、in通用操作;
  4. 列表sort搭配key/lambda实现自定义排序,可完成文本、多维数据排序;
  5. 列表推导式快速批量生成数据,简化循环代码;
  6. 序列解包 可一次性把多个元素按顺序赋给多个变量,配合星号*还能收集剩余元素,是简化多变量赋值的高频技巧;
  7. **enumerate(序列, start=起始值)**在遍历时同时返回索引和元素,配合解包即可一步拿到下标与内容,是处理带序号数据的首选写法。
相关推荐
Billy121381 小时前
Day10-C++20 Ranges(上):惰性求值与组合式数据处理
开发语言·c++进阶学习
有点。1 小时前
C++深度优先搜索(二)
开发语言·c++·深度优先
二进制杯莫停2 小时前
A和B环境的python版本相同,B环境无法安装pip依赖,离线安装
开发语言·python·pip
威联通安全存储2 小时前
TS-h1677AXU-RP 在汽车冲压车间高速冲压线检测网中的部署
python·汽车
l1t2 小时前
kryonix提交的DuckDB 统一并优化标量执行器基础设施 - #24564 PR
开发语言·数据库·数据仓库·sql
RSTJ_16253 小时前
PYTHON+AI LLM DAY ONE HUNDRED AND TWENTY-NINE
人工智能·python
夏天测3 小时前
Python 网络编程从 TCP 三次握手到 Socket 搭建极简 AI 推理服务端(零基础可跑通完整代码)
python·socket·网络通信·tcp 网络编程·零基础网络编程
Vec‑Jie3 小时前
MerchantOps-KBQA 实践(十四):本地运行、性能限制与可验证的交付边界
人工智能·后端·python·flask