列表和元组是Python最常用的两种序列。列表像"可伸缩的收纳盒",元组它像是一个"冻结"的列表。
一、列表(list)- 可变序列
1. 创建列表
python
# 空列表
empty_list = []
# 有元素的列表
students = ["小明", "小红", "小刚"]
# 混合类型列表
mixed = [100, "Python", True, 3.14]
代码解释 :用方括号[]创建列表,元素之间用逗号隔开,可以存任意类型数据。
2. 增:添加元素
python
# append():在末尾添加一个元素
students = ["小明", "小红"]
students.append("小刚")
print(students) # 输出:['小明', '小红', '小刚']
# extend():在末尾添加多个元素(拆开后添加)
students.extend(["小李", "小王"])
print(students) # 输出:['小明', '小红', '小刚', '小李', '小王']
# insert():在指定位置插入
students.insert(1, "小美") # 在索引为1的位置插入
print(students) # 输出:['小明', '小美', '小红', '小刚', '小李', '小王']
关键点 :append()加单个,extend()加序列,insert()指定位置。
3. 删:删除元素
python
nums = [10, 20, 30, 40, 50]
# del:根据索引删除
del nums[0] # 删除第0个元素
print(nums) # 输出:[20, 30, 40, 50]
# pop():删除并返回(默认最后一个)
last = nums.pop() # 删除50,并返回50
print(nums, last) # 输出:[20, 30, 40] 50
# remove():删除第一个匹配的值
nums.remove(30) # 删除30
print(nums) # 输出:[20, 40]
关键点 :del和pop()按位置删,remove()按值删。
4. 改:修改元素
python
scores = [85, 90, 78, 92]
# 直接赋值修改
scores[2] = 88 # 把第2个元素78改成88
print(scores) # 输出:[85, 90, 88, 92]
# reverse():倒序排列
scores.reverse()
print(scores) # 输出:[92, 88, 90, 85]
# sort():排序(默认升序)
scores.sort()
print(scores) # 输出:[85, 88, 90, 92]
# sort(reverse=True)降序
scores.sort(reverse=True)
print(scores) # 输出:[92, 90, 88, 85]
关键点 :reverse()只翻转,sort()会按大小排序。
5. 查:查找元素
python
fruits = ["苹果", "香蕉", "橙子", "香蕉"]
# index():找元素位置(找不到会报错)
pos = fruits.index("橙子")
print(f"橙子在位置:{pos}") # 输出:2
# count():统计出现次数
banana_count = fruits.count("香蕉")
print(f"香蕉出现了{banana_count}次") # 输出:2
# in:判断是否存在
if "苹果" in fruits:
print("有苹果") # 输出:有苹果
# not in:判断是否不存在
if "西瓜" not in fruits:
print("没有西瓜") # 输出:没有西瓜
# len():获取长度
length = len(fruits)
print(f"列表长度:{length}") # 输出:4
关键点 :in和not in最常用,简洁又安全。
6. 列表操作总结表
|-------|---------------|---------|---------|
| 操作类型 | 方法/语法 | 作用 | 是否改变原列表 |
| 增 | append(x) | 末尾加1个元素 | ✅ 是 |
| | extend(seq) | 末尾加多个元素 | ✅ 是 |
| | insert(i,x) | 指定位置插入 | ✅ 是 |
| 删 | del list[i] | 删除指定索引 | ✅ 是 |
| | pop(i) | 删除并返回值 | ✅ 是 |
| | remove(x) | 删除第一个x | ✅ 是 |
| 改 | list[i]=x | 修改元素 | ✅ 是 |
| | reverse() | 倒序 | ✅ 是 |
| | sort() | 排序 | ✅ 是 |
| 查 | index(x) | 查找位置 | ❌ 否 |
| | count(x) | 统计次数 | ❌ 否 |
| | len(list) | 获取长度 | ❌ 否 |
| | x in list | 判断存在 | ❌ 否 |
二、元组(tuple)- 不可变序列
1. 元组特点与创建
🔍 数据类型支持
元组非常灵活,它可以存放任意类型的数据,甚至可以嵌套其他复杂数据结构:
- 基本数据类型: 整数 (
int)、浮点数 (float)、字符串 (str)、布尔值 (bool)。- 复杂数据类型: 列表 (
list)、字典 (dict)、集合 (set)、甚至是另一个元组 (tuple)。
python
# 元组用小括号
info = ("张三", 25, "工程师")
# 空元组
empty = ()
# ❗单元素元组必须加逗号!
single = (10,) # 正确,是元组
not_tuple = (10) # 错误,这只是数字10
print(type(single)) # 输出:<class 'tuple'>
print(type(not_tuple)) # 输出:<class 'int'>
代码解释:单元素元组一定要加逗号,否则Python会当成普通数据。
关键点:元组一旦创建,就不能增删改,像"只读文件"。
2. 元组的基本操作
python
coordinates = (100, 200, 300, 200)
# 索引查找
x = coordinates[0] # 获取第0个元素
print(f"x坐标:{x}") # 输出:100
# index()查找位置
pos = coordinates.index(200)
print(f"200第一次出现在位置:{pos}") # 输出:1
# count()统计次数
count_200 = coordinates.count(200)
print(f"200出现了{count_200}次") # 输出:2
# len()获取长度
length = len(coordinates)
print(f"元组长度:{length}") # 输出:4
关键点:元组只有查的操作,没有增删改。所以比列表更安全、速度更快。
3. 元组基本操作总结表
|--------------|------|----------------|------|
| 操作方法 | 作用 | 示例 | 返回值 |
| t[i] | 索引访问 | t[0] | 元素值 |
| t.index(x) | 查找位置 | t.index(200) | 索引整数 |
| t.count(x) | 统计次数 | t.count(200) | 整数次数 |
| len(t) | 获取长度 | len(t) | 整数长度 |
三、列表 vs 元组:怎么选?
|----------|-----------|---------------|
| 对比项 | 列表 | 元组 |
| 符号 | [] | () |
| 可变性 | ✅ 可以修改 | ❌ 不能修改 |
| 速度 | 较慢 | 更快 |
| 安全 | 易误改 | 防止误改 |
| 用途 | 动态数据 | 固定数据 |
| 场景举例 | 学生名单、待办事项 | 坐标、RGB颜色、配置信息 |
一句话建议 :数据会变就用列表,数据固定就用元组。
四、常见错误提醒
python
# 错误1:修改元组
t = (1, 2, 3)
t[0] = 10 # TypeError: 'tuple' object does not support item assignment
# 错误2:元组只有一个元素不加逗号
t = (10) # 这不是元组!
# 错误3:删除列表元素后索引错乱
nums = [1, 2, 3, 4]
del nums[1] # 删除2
print(nums[1]) # 现在nums[1]是3,不是2
五、总结
- 列表:可变、灵活、常用,几乎所有动态数据都用它
- 元组:不可变、安全、快速,适合固定数据
- 核心区别:能不能改
六、 元组进阶操作
切片: 提取子元组,如 my_tuple[1:3]。
连接与重复: 可以使用 + 拼接两个元组,或使用 * 重复元组(这会生成新的元组)。
解包(Unpacking): 非常实用的功能,可以将元组的元素赋值给多个变量,例如 x, y = (10, 20)。给出这三个示例的代码
❗ 注意:虽然元组是不可变的,但这些操作会生成新的元组对象
python
# 1. 切片 (Slicing)
print("=== 1. 切片操作 ===")
original_tuple = (10, 20, 30, 40, 50)
# 提取索引 1 到 3 (不包含索引 3) 的元素
sub_tuple = original_tuple[1:3]
print(f"切片 [1:3] 的结果: {sub_tuple}") # 输出: (20, 30)
# ==========================================
# 2. 连接与重复 (Concatenation & Repetition)
print("\n=== 2. 连接与重复操作 ===")
tuple_a = (1, 2)
tuple_b = (3, 4)
# 连接:使用 + 号将两个元组合并成一个新的元组
combined_tuple = tuple_a + tuple_b
print(f"A + B 的结果: {combined_tuple}") # 输出: (1, 2, 3, 4)
# 重复:使用 * 号将元组重复多次
repeated_tuple = tuple_a * 3
print(f"A 重复 3 次的结果: {repeated_tuple}") # 输出: (1, 2, 1, 2, 1, 2)
# 原来的 tuple_a 和 tuple_b 依然保持不变
# 注意:虽然元组是不可变的,但这些操作会生成新的元组对象
# ==========================================
# 3. 解包 (Unpacking)
# 场景 A:基本解包
coordinates = (100, 200)
x, y = coordinates # 将元组中的值分别赋给 x 和 y
print(f"坐标解包 - x: {x}, y: {y}") # 坐标解包 - x: 100, y: 200
# 场景 B:函数返回多个值(非常常见的用法)
def get_name_age():
return "Alice", 30 # 返回一个元组
# 直接解包函数返回值
name, age = get_name_age()
print(f"姓名: {name}, 年龄: {age}") # 姓名: Alice, 年龄: 30
# 场景 C:使用 * 来捕获多余的值
# 如果变量数量少于元组长度,可以使用 * 来收集剩余的元素
numbers = (1, 2, 3, 4, 5)
first, second, *rest = numbers
print(f"第一个: {first}, 第二个: {second}, 剩余的: {rest}")
# 输出: 第一个: 1, 第二个: 2, 剩余的: [3, 4, 5] (❗注意 rest 是一个列表)
# 场景 D:交换变量(Python 中非常优雅的写法)
a = 5
b = 10
print(f"交换前: a={a}, b={b}") # 交换前: a=5, b=10
a, b = b, a # 利用元组解包交换数值
print(f"交换后: a={a}, b={b}") # 交换后: a=10, b=5
1. 元组进阶操作总结
|------------------------|------------------------|---------------|--------------------------------------|------------------------------|
| 操作类型 | 语法/方法 | 功能描述 | 关键特点 | 示例/备注 |
| 切片 (Slicing) | tuple[start:end] | 提取元组中指定范围的元素 | - 返回新元组 - 包含start索引,不包含end索引 - 原元组不变 | t[1:3] 提取索引1到2的元素 |
| 连接 (Concatenation) | + 运算符 | 将两个元组合并为一个新元组 | - 创建新对象 - 原元组保持不变 | (1,2) + (3,4) = (1,2,3,4) |
| 重复 (Repetition) | * 运算符 | 将元组重复指定次数 | - 创建新对象 - 原元组保持不变 | (1,2)*3 = (1,2,1,2,1,2) |
| 基本解包 (Unpacking) | var1, var2 = tuple | 将元组元素赋值给多个变量 | - 变量数量必须与元组长度匹配 - 常用于函数返回值 | x, y = (100, 200) |
| 扩展解包 | first, *rest = tuple | 使用*收集剩余元素 | - *变量接收列表类型 - 灵活处理不定长元组 | first, *rest = (1,2,3,4,5) |
| 变量交换 | a, b = b, a | 交换两个变量的值 | - Python特有优雅写法 - 利用元组解包机制 | 无需临时变量 |
2. 重要特性说明:
- 不可变性:元组本身不可修改,但相关操作会返回新元组
- 内存效率:由于不可变,元组比列表更节省内存
- 常用场景:
-
- 函数返回多个值
- 字典键(因为可哈希)
- 保护数据不被修改
- 线程安全的数据结构
3. 解包的特殊用法:
*args在函数定义中收集位置参数**kwargs在函数定义中收集关键字参数(字典解包)- 嵌套解包:
a, (b, c) = (1, (2, 3))
这些操作展示了Python元组在保持不可变性的同时,如何通过灵活的操作提供强大的功能。