Python 学习笔记(第五期)——组合数据类型:列表、元组、集合与字典精讲
Python 学习笔记(第五期)——组合数据类型:列表、元组、集合与字典精讲
更多Python知识:Python基础入门
我的主页:AOwhisky,这里有更多运维系统性知识整理和其他有趣内容,欢迎与我一起探讨学习~
📖 引言:数据的“收纳艺术”
在前四期中,我们已经掌握了Python的基础语法、运算符和流程控制,能够编写出具有一定逻辑的程序。但程序要处理的数据往往不是孤立的——我们可能需要存储一组学生的姓名、记录一个班级的成绩表、维护一个用户的信息档案……这些场景都涉及到批量数据的组织与管理。
如果说基础数据类型(数字、字符串)是零散的“零件”,那么组合数据类型就是“收纳盒”——它们将多个数据组织成一个整体,让程序能够更高效地管理和操作数据。Python提供了四种核心的组合数据类型:列表(List)、元组(Tuple)、集合(Set) 和 字典(Dict),它们各自有不同的特性和适用场景。
本期将系统学习这四种数据类型的创建、访问、操作和高级用法,并通过“十大歌手评分”和“手机通讯录”两个实战项目,将理论知识落地为可运行的程序。
📑 本期目录
- 认识组合数据类型(序列、集合、映射)
- 列表(List)——创建、访问、添加、删除、排序、推导式
- 元组(Tuple)——不可变序列的创建与访问
- 集合(Set)——唯一无序元素的创建与操作
- 字典(Dict)——键值对的创建、访问、修改与删除
- 组合数据类型通用运算符(
+、*、in、not in) - 综合实战演练(两个完整案例)
- 总结与知识点一览表
正文
一、认识组合数据类型
组合数据类型将多个相同类型或不同类型的数据组织为一个整体。根据数据组织方式的不同,Python的组合数据类型可分为三大类:
| 类别 | 包含类型 | 核心特征 |
|---|---|---|
| 序列类型(Sequence) | 字符串(str)、列表(list)、元组(tuple) | 有序、支持索引和切片 |
| 集合类型(Set) | 集合(set) | 无序、元素唯一 |
| 映射类型(Mapping) | 字典(dict) | 键值对、键唯一 |
序列类型的双向索引:
Python中的序列支持正向递增索引和反向递减索引,这使得访问元素非常灵活。
字符串 "Python" 的索引示例:
正向索引: 0 1 2 3 4 5
┌────┬────┬────┬────┬────┬────┐
│ P │ y │ t │ h │ o │ n │
└────┴────┴────┴────┴────┴────┘
反向索引: -6 -5 -4 -3 -2 -1
text = "Python"
print(text[0]) # P(正向索引)
print(text[-1]) # n(反向索引)
print(text[1:4]) # yth(切片,不包含结束索引)
二、列表(List)——灵活的数据“购物车”
列表是Python中最灵活的序列类型,它没有长度限制,可以包含任意类型、任意数量的元素。列表是可变的——创建后可以随意增删改元素。
2.1 创建列表
# 方法一:使用中括号 [] 直接创建
list_empty = [] # 空列表
list_numbers = [1, 2, 3, 4, 5] # 数字列表
list_mixed = [1, "hello", 3.14, True] # 混合类型(允许)
# 方法二:使用 list() 函数创建
list_from_str = list("Python") # ['P', 'y', 't', 'h', 'o', 'n']
list_from_range = list(range(5)) # [0, 1, 2, 3, 4]
💡 白话理解:列表就像一个购物车——你可以在里面放任何东西(任意类型),随时往里面加商品(append)、拿出来(remove)、调整顺序(sort),非常灵活。
2.2 访问列表元素
fruits = ["苹果", "香蕉", "橙子", "葡萄", "西瓜"]
# 1. 索引访问
print(fruits[0]) # 苹果(正向索引)
print(fruits[-1]) # 西瓜(反向索引)
# 2. 切片访问(返回新列表)
print(fruits[1:4]) # ['香蕉', '橙子', '葡萄']
print(fruits[::2]) # ['苹果', '橙子', '西瓜'](步长2)
print(fruits[::-1]) # ['西瓜', '葡萄', '橙子', '香蕉', '苹果'](反转)
# 3. 循环遍历
for fruit in fruits:
print(fruit, end=" ") # 苹果 香蕉 橙子 葡萄 西瓜
切片语法详解:
| 写法 | 含义 | 示例(fruits = [‘苹果’,‘香蕉’,‘橙子’,‘葡萄’,‘西瓜’]) |
|---|---|---|
list[start:end] |
从 start 到 end-1 | fruits[1:4] → ['香蕉','橙子','葡萄'] |
list[start:] |
从 start 到末尾 | fruits[2:] → ['橙子','葡萄','西瓜'] |
list[:end] |
从开头到 end-1 | fruits[:3] → ['苹果','香蕉','橙子'] |
list[::step] |
按步长取全部 | fruits[::2] → ['苹果','橙子','西瓜'] |
list[::-1] |
反转列表 | fruits[::-1] → ['西瓜','葡萄','橙子','香蕉','苹果'] |
2.3 添加列表元素
| 方法 | 作用 | 示例 | 结果 |
|---|---|---|---|
append(x) |
在末尾添加单个元素 | [1,2].append(3) |
[1,2,3] |
extend(iterable) |
在末尾添加多个元素(合并列表) | [1,2].extend([3,4]) |
[1,2,3,4] |
insert(i, x) |
在指定位置插入元素 | [1,2,3].insert(1, 99) |
[1,99,2,3] |
numbers = [1, 2, 3]
# append:末尾添加
numbers.append(4)
print(numbers) # [1, 2, 3, 4]
# extend:合并列表
numbers.extend([5, 6])
print(numbers) # [1, 2, 3, 4, 5, 6]
# insert:指定位置插入
numbers.insert(0, 0) # 在索引0处插入0
print(numbers) # [0, 1, 2, 3, 4, 5, 6]
⚠️ 注意:
append()和extend()的区别常被混淆——append(x)将 x 作为一个整体添加;extend(iterable)将可迭代对象中的每个元素逐个添加。
lst = [1, 2]
lst.append([3, 4]) # 将整个列表作为一个元素添加
print(lst) # [1, 2, [3, 4]]
lst2 = [1, 2]
lst2.extend([3, 4]) # 逐个添加元素
print(lst2) # [1, 2, 3, 4]
2.4 删除列表元素
| 方法 | 作用 | 示例 | 结果 |
|---|---|---|---|
del list[i] |
删除指定索引的元素 | del [1,2,3][0] |
[2,3] |
remove(x) |
删除第一个匹配的元素 | [1,2,1].remove(1) |
[2,1] |
pop(i) |
弹出指定索引的元素(默认末尾) | [1,2,3].pop(1) |
返回2,列表变为 [1,3] |
clear() |
清空列表所有元素 | [1,2].clear() |
[] |
fruits = ["苹果", "香蕉", "橙子", "香蕉"]
# del:按索引删除
del fruits[0]
print(fruits) # ['香蕉', '橙子', '香蕉']
# remove:按值删除(只删除第一个匹配)
fruits.remove("香蕉")
print(fruits) # ['橙子', '香蕉']
# pop:弹出并返回元素
last = fruits.pop()
print(last) # 香蕉
print(fruits) # ['橙子']
# clear:清空
fruits.clear()
print(fruits) # []
2.5 列表排序
| 方法 | 作用 | 是否原地修改 | 返回值 |
|---|---|---|---|
list.sort() |
升序排列 | ✅ 是 | None |
list.sort(reverse=True) |
降序排列 | ✅ 是 | None |
sorted(list) |
升序排列 | ❌ 否 | 新列表 |
list.reverse() |
反转列表顺序 | ✅ 是 | None |
numbers = [6, 2, 5, 3, 1, 4]
# sort:原地排序(升序)
numbers.sort()
print(numbers) # [1, 2, 3, 4, 5, 6]
# sort:原地排序(降序)
numbers.sort(reverse=True)
print(numbers) # [6, 5, 4, 3, 2, 1]
# sorted:返回新列表,原列表不变
original = [3, 1, 4, 1, 5]
new_sorted = sorted(original)
print(original) # [3, 1, 4, 1, 5](不变)
print(new_sorted) # [1, 1, 3, 4, 5](新列表)
# reverse:反转列表
words = ["a", "b", "c"]
words.reverse()
print(words) # ['c', 'b', 'a']
# 按字符串长度排序
fruits = ["apple", "fig", "banana", "kiwi"]
fruits.sort(key=len)
print(fruits) # ['fig', 'kiwi', 'apple', 'banana']
2.6 列表推导式
列表推导式是Python中非常优雅的特性,它可以用一行代码生成新的列表,替代传统的 for 循环。
# 基本语法:[表达式 for 变量 in 可迭代对象]
# 传统写法 vs 列表推导式
# 传统写法(生成1~10的平方)
squares = []
for i in range(1, 11):
squares.append(i ** 2)
print(squares) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 列表推导式(一行搞定)
squares = [i ** 2 for i in range(1, 11)]
print(squares) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
带条件的列表推导式:
# 只保留1~20中的偶数
evens = [i for i in range(1, 21) if i % 2 == 0]
print(evens) # [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
嵌套循环的列表推导式:
# 两个列表的元素两两相加
list1 = [1, 2, 3]
list2 = [10, 20, 30]
result = [x + y for x in list1 for y in list2]
print(result) # [11, 21, 31, 12, 22, 32, 13, 23, 33]
三、元组(Tuple)——不可变的“密封档案盒”
元组与列表非常相似,但有一个核心区别:元组一旦创建,就不能修改(不可变)。正因为不可变,元组在某些场景下更加安全和高效。
3.1 创建元组
# 方法一:使用圆括号 ()
tuple_empty = () # 空元组
tuple_numbers = (1, 2, 3, 4, 5) # 数字元组
tuple_mixed = (1, "hello", 3.14, True) # 混合类型
# ⚠️ 单元素元组的特殊写法(必须加逗号)
single_element = (5,) # 这是一个元组
not_tuple = (5) # 这是整数 5(不是元组!)
# 方法二:使用 tuple() 函数
tuple_from_list = tuple([1, 2, 3]) # (1, 2, 3)
tuple_from_str = tuple("Python") # ('P', 'y', 't', 'h', 'o', 'n')
⚠️ 常见误区:
(5)不是元组,Python 会将其解释为整数 5。单元素元组必须加逗号:(5,)。
3.2 访问元组元素
元组的访问方式与列表完全相同——支持索引、切片和循环遍历。
t = ("a", "b", "c", "d", "e")
print(t[0]) # a
print(t[-1]) # e
print(t[1:4]) # ('b', 'c', 'd')
for item in t:
print(item, end=" ") # a b c d e
3.3 元组的不可变性
t = (1, 2, 3)
# ❌ 以下操作都会报错
# t[0] = 100 # TypeError: 'tuple' object does not support item assignment
# t.append(4) # AttributeError: 'tuple' object has no attribute 'append'
# t.remove(2) # AttributeError: 'tuple' object has no attribute 'remove'
元组 vs 列表对比:
| 对比维度 | 列表(List) | 元组(Tuple) |
|---|---|---|
| 是否可变 | ✅ 可变 | ❌ 不可变 |
| 是否有序 | ✅ 有序 | ✅ 有序 |
| 使用场景 | 动态数据集合 | 固定数据(如坐标、配置) |
| 性能 | 较慢(需分配额外内存) | 更快(内存占用小) |
| 作为字典键 | ❌ 不允许 | ✅ 允许 |
四、集合(Set)——唯一无序的“去重收纳盒”
集合的特点是元素唯一且无序。它常用于去重和集合运算(交集、并集、差集)。
4.1 创建集合
# 方法一:使用大括号 {}
set_empty = set() # ⚠️ {} 是空字典,不是空集合!
set_numbers = {1, 2, 3, 4, 5}
set_mixed = {1, "hello", 3.14}
# 方法二:使用 set() 函数
set_from_list = set([1, 2, 2, 3, 3, 4]) # {1, 2, 3, 4}(自动去重)
set_from_str = set("hello") # {'h', 'e', 'l', 'o'}(顺序不定)
# ⚠️ 空集合只能用 set() 创建
print(type({})) # <class 'dict'>
print(type(set())) # <class 'set'>
💡 白话理解:集合像一个自动去重的收纳盒——你扔进去重复的东西,它只会保留一份,而且东西的摆放没有固定顺序。
4.2 集合的常见操作
| 方法 | 作用 | 示例 |
|---|---|---|
add(x) |
添加元素 x(已存在则不做任何事) | {1,2}.add(3) → {1,2,3} |
remove(x) |
删除元素 x(不存在则报错) | {1,2}.remove(1) → {2} |
discard(x) |
删除元素 x(不存在不报错) | {1,2}.discard(3) → {1,2} |
pop() |
随机删除并返回一个元素 | {1,2}.pop() → 返回1或2 |
clear() |
清空集合 | {1,2}.clear() → set() |
s = {1, 2, 3}
# 添加元素
s.add(4)
print(s) # {1, 2, 3, 4}
s.add(2) # 已存在,不做任何事
print(s) # {1, 2, 3, 4}
# 删除元素
s.remove(1)
print(s) # {2, 3, 4}
# s.remove(99) # KeyError: 99(不存在会报错)
s.discard(99) # 不存在但不报错
print(s) # {2, 3, 4}
# 随机弹出
popped = s.pop()
print(f"弹出:{popped},剩余:{s}")
4.3 集合运算
| 运算 | 运算符 | 方法 | 说明 |
|---|---|---|---|
| 并集 | ` | ` | union() |
| 交集 | & |
intersection() |
两个集合共有的元素 |
| 差集 | - |
difference() |
在 A 中但不在 B 中的元素 |
| 对称差集 | ^ |
symmetric_difference() |
不同时在 A 和 B 中的元素 |
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
print(A | B) # {1, 2, 3, 4, 5, 6, 7, 8}(并集)
print(A & B) # {4, 5}(交集)
print(A - B) # {1, 2, 3}(差集)
print(A ^ B) # {1, 2, 3, 6, 7, 8}(对称差集)
4.4 集合推导式
# 生成 1~10 中偶数的集合
evens = {i for i in range(1, 11) if i % 2 == 0}
print(evens) # {2, 4, 6, 8, 10}
五、字典(Dict)——键值对的“新华字典”
字典是Python中唯一的映射类型,它以键值对(key: value) 的形式存储数据,通过“键”快速查找对应的“值”。
5.1 创建字典
# 方法一:使用大括号 {}
dict_empty = {} # 空字典
dict_person = {"name": "张三", "age": 18, "city": "北京"}
# 方法二:使用 dict() 函数
dict_from_kwargs = dict(name="张三", age=18, city="北京") # 键名不加引号
dict_from_pairs = dict([("name", "张三"), ("age", 18)]) # 从键值对列表创建
# ⚠️ 字典的键必须是不可变类型
# ✅ 合法键:字符串、数字、元组
# ❌ 非法键:列表、字典(可变类型)
💡 白话理解:字典就像一本新华字典——通过“部首/拼音”(键)快速找到对应的“释义”(值),查找速度极快。
5.2 访问字典元素
person = {"name": "张三", "age": 18, "city": "北京"}
# 方法一:通过键访问(键不存在时会报错 KeyError)
print(person["name"]) # 张三
# print(person["score"]) # KeyError: 'score'
# 方法二:使用 get() 方法(键不存在时返回 None 或指定默认值)
print(person.get("name")) # 张三
print(person.get("score")) # None(不报错)
print(person.get("score", 0)) # 0(指定默认值)
# 方法三:遍历字典
# 遍历键(默认)
for key in person:
print(key, ":", person[key])
# 遍历键值对
for key, value in person.items():
print(f"{key} = {value}")
5.3 添加与修改字典元素
person = {"name": "张三", "age": 18}
# 添加新元素(键不存在)
person["city"] = "北京"
print(person) # {'name': '张三', 'age': 18, 'city': '北京'}
# 修改已有元素(键已存在)
person["age"] = 19
print(person) # {'name': '张三', 'age': 19, 'city': '北京'}
# 使用 update() 批量更新
person.update({"age": 20, "job": "工程师"})
print(person) # {'name': '张三', 'age': 20, 'city': '北京', 'job': '工程师'}
5.4 删除字典元素
person = {"name": "张三", "age": 18, "city": "北京", "job": "工程师"}
# pop(key):删除指定键,返回对应的值
removed = person.pop("city")
print(removed) # 北京
print(person) # {'name': '张三', 'age': 18, 'job': '工程师'}
# popitem():随机删除一个键值对(Python 3.7+ 删除最后一个插入的)
last = person.popitem()
print(last) # ('job', '工程师')
print(person) # {'name': '张三', 'age': 18}
# clear():清空
person.clear()
print(person) # {}
5.5 字典推导式
# 交换字典的键和值
original = {"name": "张三", "age": 18, "city": "北京"}
swapped = {value: key for key, value in original.items()}
print(swapped) # {'张三': 'name', 18: 'age', '北京': 'city'}
六、组合数据类型通用运算符
| 运算符 | 适用类型 | 作用 | 示例 |
|---|---|---|---|
+ |
字符串、列表、元组 | 拼接 | [1,2] + [3,4] → [1,2,3,4] |
* |
字符串、列表、元组 | 重复拼接 | [1,2] * 3 → [1,2,1,2,1,2] |
in |
所有序列 + 集合 + 字典(键) | 判断是否存在 | "a" in ["a","b"] → True |
not in |
所有序列 + 集合 + 字典(键) | 判断是否不存在 | "c" not in ["a","b"] → True |
# + 拼接
print([1, 2, 3] + [4, 5, 6]) # [1, 2, 3, 4, 5, 6]
print((1, 2) + (3, 4)) # (1, 2, 3, 4)
# * 重复
print([1, 2] * 3) # [1, 2, 1, 2, 1, 2]
print("-" * 30) # ------------------------------
# in / not in
print(3 in [1, 2, 3]) # True
print("name" in {"name": "张三"}) # True(判断键)
print("张三" in {"name": "张三"}) # False(判断键,不是值)
七、综合实战演练
实战一:十大歌手评分系统
需求描述:校园十大歌手比赛中,10位评委为每位选手打分。计算选手的最终得分时,需要去掉一个最高分和一个最低分,然后计算剩余分数的平均分。请实现该功能。
涉及知识点:列表创建、排序、切片、sum() 求和
# 十大歌手评分系统
# 评委打分(模拟10位评委的打分)
scores = [9.5, 8.8, 9.2, 7.5, 9.8, 9.0, 8.5, 9.3, 8.9, 9.1]
print(f"原始打分:{scores}")
# 对分数排序
scores.sort()
print(f"排序后: {scores}")
# 去掉一个最高分和一个最低分(切片)
# 去掉第1个(最低分)和最后1个(最高分)
valid_scores = scores[1:-1]
print(f"有效分数:{valid_scores}")
# 计算平均分(保留两位小数)
average = sum(valid_scores) / len(valid_scores)
print(f"最终得分:{average:.2f} 分")
运行结果:
原始打分:[9.5, 8.8, 9.2, 7.5, 9.8, 9.0, 8.5, 9.3, 8.9, 9.1]
排序后: [7.5, 8.5, 8.8, 8.9, 9.0, 9.1, 9.2, 9.3, 9.5, 9.8]
有效分数:[8.5, 8.8, 8.9, 9.0, 9.1, 9.2, 9.3, 9.5]
最终得分:9.04 分
逐行解读:
| 代码 | 作用 |
|---|---|
scores.sort() |
将分数从小到大排序 |
scores[1:-1] |
切片去掉第一个(最低分)和最后一个(最高分) |
sum(valid_scores) |
计算有效分数的总和 |
len(valid_scores) |
计算有效分数的个数 |
average = sum / len |
计算平均分 |
{average:.2f} |
格式化为保留两位小数 |
实战二:手机通讯录管理系统
需求描述:实现一个基于字典的手机通讯录管理程序,支持以下功能:
- 添加联系人:输入姓名和电话,存入通讯录
- 查看联系人:输入姓名,显示对应的电话号码
- 修改联系人:输入姓名和新电话,更新信息
- 删除联系人:输入姓名,从通讯录中删除
- 显示全部:列出所有联系人
- 退出:退出程序
涉及知识点:字典的增删改查、while 循环、if-elif-else 多分支
# 手机通讯录管理系统
contacts = {} # 空字典,用于存储联系人 {姓名: 电话}
def show_menu():
"""显示功能菜单"""
print("\n" + "=" * 30)
print(" 📱 手机通讯录")
print("=" * 30)
print("1. 添加联系人")
print("2. 查看联系人")
print("3. 修改联系人")
print("4. 删除联系人")
print("5. 显示全部联系人")
print("0. 退出")
print("=" * 30)
while True:
show_menu()
choice = input("请选择功能(0-5):")
if choice == "0":
print("👋 感谢使用,再见!")
break
elif choice == "1":
# 添加联系人
name = input("请输入联系人姓名:")
if name in contacts:
print(f"⚠️ 联系人 {name} 已存在!")
continue
phone = input("请输入电话号码:")
contacts[name] = phone
print(f"✅ 已添加联系人:{name} -> {phone}")
elif choice == "2":
# 查看联系人
name = input("请输入要查询的姓名:")
if name in contacts:
print(f"📞 {name} 的电话是:{contacts[name]}")
else:
print(f"❌ 未找到联系人:{name}")
elif choice == "3":
# 修改联系人
name = input("请输入要修改的姓名:")
if name in contacts:
new_phone = input(f"请输入 {name} 的新电话:")
contacts[name] = new_phone
print(f"✅ 已更新 {name} 的电话为:{new_phone}")
else:
print(f"❌ 未找到联系人:{name}")
elif choice == "4":
# 删除联系人
name = input("请输入要删除的姓名:")
if name in contacts:
confirm = input(f"确认删除 {name} 吗?(y/n):")
if confirm.lower() == "y":
del contacts[name]
print(f"✅ 已删除联系人:{name}")
else:
print(f"❌ 未找到联系人:{name}")
elif choice == "5":
# 显示全部联系人
if not contacts:
print("📭 通讯录为空")
else:
print("\n📋 全部联系人:")
print("-" * 30)
# 使用 items() 遍历键值对
for name, phone in contacts.items():
print(f" {name} : {phone}")
print("-" * 30)
print(f"共 {len(contacts)} 位联系人")
else:
print("❌ 无效输入,请重新选择!")
运行示例:
==============================
📱 手机通讯录
==============================
1. 添加联系人
2. 查看联系人
3. 修改联系人
4. 删除联系人
5. 显示全部联系人
0. 退出
==============================
请选择功能(0-5):1
请输入联系人姓名:张三
请输入电话号码:13800138000
✅ 已添加联系人:张三 -> 13800138000
==============================
...
==============================
请选择功能(0-5):5
📋 全部联系人:
------------------------------
张三 : 13800138000
------------------------------
共 1 位联系人
八、补充知识:类型判断与可变性
8.1 使用 isinstance() 判断类型
print(isinstance([1, 2, 3], list)) # True
print(isinstance((1, 2), tuple)) # True
print(isinstance({1, 2}, set)) # True
print(isinstance({"a": 1}, dict)) # True
8.2 可变与不可变类型总结
| 类型 | 可变性 | 作为字典键 | 作为集合元素 |
|---|---|---|---|
| int | ❌ 不可变 | ✅ 允许 | ✅ 允许 |
| float | ❌ 不可变 | ✅ 允许 | ✅ 允许 |
| str | ❌ 不可变 | ✅ 允许 | ✅ 允许 |
| tuple | ❌ 不可变 | ✅ 允许 | ✅ 允许 |
| list | ✅ 可变 | ❌ 不允许 | ❌ 不允许 |
| set | ✅ 可变 | ❌ 不允许 | ❌ 不允许 |
| dict | ✅ 可变 | ❌ 不允许 | ❌ 不允许 |
核心规则:字典的键和集合的元素必须是不可变类型(hashable)。因此列表、集合、字典不能作为字典的键或集合的元素。
📝 总结与知识点一览表
核心知识点汇总
| 数据类型 | 符号 | 可变性 | 有序性 | 唯一性 | 创建示例 |
|---|---|---|---|---|---|
| 列表(list) | [] |
✅ 可变 | ✅ 有序 | ❌ 允许重复 | [1, 2, "a"] |
| 元组(tuple) | () |
❌ 不可变 | ✅ 有序 | ❌ 允许重复 | (1, 2, "a") |
| 集合(set) | {}(无键值对) |
✅ 可变 | ❌ 无序 | ✅ 必须唯一 | {1, 2, 3} |
| 字典(dict) | {key: value} |
✅ 可变 | ❌ 无序(Py3.7+按插入顺序) | 键必须唯一 | {"name": "Tom"} |
常用操作速查表
| 操作 | 列表 | 元组 | 集合 | 字典 |
|---|---|---|---|---|
| 创建 | [1,2] |
(1,2) |
{1,2} |
{"a":1} |
| 索引访问 | ✅ lst[0] |
✅ t[0] |
❌ | ✅ d["a"] |
| 切片 | ✅ | ✅ | ❌ | ❌ |
| 添加元素 | append(), insert() |
❌ | add(), update() |
d["k"] = v |
| 删除元素 | remove(), pop(), del |
❌ | remove(), pop() |
pop(), del |
| 修改元素 | lst[0] = x |
❌ | ❌ | d["k"] = v |
| 成员判断 | in |
in |
in |
in(判断键) |
| 推导式 | ✅ [x for x in ...] |
❌ | ✅ {x for x in ...} |
✅ {k:v for ...} |
| 作为字典键 | ❌ | ✅ | ❌ | ❌ |
常见错误排查指南
| 错误现象 | 大概率原因 | 解决方案 |
|---|---|---|
TypeError: unhashable type: 'list' |
尝试用列表作为字典的键或集合元素 | 改用元组(不可变类型) |
KeyError: 'xxx' |
访问字典中不存在的键 | 使用 dict.get(key, default) 代替 dict[key] |
AttributeError: 'tuple' object has no attribute 'append' |
误以为元组可以修改 | 确认是否需要使用列表替代元组 |
| 遍历列表时删除元素出现意外结果 | 遍历时修改了列表长度 | 遍历副本 for item in list[:]: |
TypeError: 'int' object is not iterable |
对数字使用了 for...in... |
使用 range() 生成序列 |
| 列表推导式结果为空 | 条件写错或误用 | 检查 if 条件的逻辑 |
学习/生产最佳实践
- 选择合适的数据类型:需要动态增删改 → 列表;需要保护数据不被修改 → 元组;需要去重 → 集合;需要键值对快速查找 → 字典。
- 列表推导式提升代码简洁性:能用列表推导式的地方,尽量用它替代
for循环,代码更简洁、更 Pythonic。 - 字典优先使用
get():访问字典时优先使用get()方法,避免KeyError导致程序崩溃。 - 注意不可变性的约束:字典的键和集合的元素必须是不可变类型,这是经常被忽视的约束条件。
- 浅拷贝 vs 深拷贝:列表的
copy()和切片[:]都是浅拷贝,嵌套列表等复杂结构需要使用copy.deepcopy()。
🔜 下期预告
本期我们系统学习了Python的四种组合数据类型——列表(购物车式动态集合)、元组(密封档案盒)、集合(自动去重收纳盒)和字典(新华字典式键值对映射),并通过“十大歌手评分”和“手机通讯录”两个实战项目,将这些数据类型应用到实际场景中。
下一期,我们将进入 函数 的世界——学习如何将重复的代码封装成可复用的函数,掌握函数的定义与调用、参数传递(位置参数、关键字参数、默认参数、*args 和 **kwargs)、返回值、变量作用域(LEGB原则)、以及递归函数和匿名函数(lambda)等高级用法。同时,我们还将通过“角谷猜想”、“饮料自动售货机”、“兔子数列”和“归并排序”等实战项目,将函数式编程思想应用到实际开发中。敬请期待!
更多推荐


所有评论(0)