注:学习资料来源<尚硅谷>
视频:点击跳转
代码仓库:pythonStudy
在编程中,我们经常需要同时处理多个数据,比如存储全班同学的成绩、管理商品库存或分析一长串测量值。如果把一条数据看作一件物品,这些物品就需要一个容器来统一收纳。Python 提供了五种强大的内置数据容器:列表、元组、字符串、集合、字典。它们各有特点,适用于不同场景。本文将从零介绍每种容器的用法,并给出大量实例和常见操作,帮你彻底掌握它们。
1. 列表(list)—— 最灵活的序列
列表可以存放一组有序的数据,并且允许你随时增、删、改、查其中的元素。它就像一个可伸缩的收纳盒,按顺序装下任何东西。
1.1 定义列表
使用方括号 [],元素之间用逗号分隔。元素可以是任意类型,甚至能嵌套另一个列表。
list1 = [34, 56, 21, 56, 11]
list2 = ['北京', 'Python', '你好']
list3 = [23, 'Python', True, None]
list4 = [23, 'Python', True, None, [100, 200, 300]] # 嵌套列表
empty = [] # 空列表
also_empty = list() # 另一种空列表1.2 通过下标访问元素
列表中的每个元素都有一个位置编号,称为下标或索引。正索引从 0 开始,负索引从 -1 开始表示倒数第一个。
nums = [10, 20, 30, 40, 50]
print(nums[0]) # 10
print(nums[-1]) # 50
# 嵌套列表的取值
nested = [10, 20, ['Python', '数据科学'], 40]
print(nested[2][1]) # 数据科学使用下标时,索引不能超出范围,否则会引发
IndexError。
1.3 增删改查,四两拨千斤
列表提供了丰富的方法来维护内容。
# ---------- 新增 ----------
nums = [10, 20, 30]
nums.append(40) # 尾部追加 ➜ [10,20,30,40]
nums.insert(1, 999) # 指定位置插入 ➜ [10,999,20,30,40]
nums.extend([50, 60]) # 扩展多个元素 ➜ [10,999,20,30,40,50,60]
# ---------- 删除 ----------
nums = [10, 20, 10, 40, 50]
nums.pop(1) # 删除索引1的元素并返回它
nums.remove(10) # 删除第一个值为10的元素
del nums[2] # 通过 del 语句删除
nums.clear() # 清空整个列表
# ---------- 修改 ----------
nums = [10, 20, 30]
nums[1] = 200 # 直接通过索引赋值
# ---------- 查询 ----------
nums = [10, 20, 10, 40]
print(nums[0]) # 按索引读
print(nums.index(10)) # 返回10首次出现的索引,输出 0
print(nums.count(10)) # 统计10的出现次数,输出 21.4 排序与反转
nums = [23, 11, 32, 30, 17]
nums.reverse() # 原地反转 ➜ [17,30,32,11,23]
nums.sort() # 升序排序(默然从小到大)
nums.sort(reverse=True) # 降序排序
# 字符串按 Unicode 编码排序
citys = ['北京', '上海', '广州']
citys.sort() # ➜ ['上海', '北京', '广州']
sort()和reverse()都会直接修改原列表。若想保留原列表并生成新结果,可以使用内置函数sorted()和reversed()。
1.5 适用于所有容器的内置函数
这些函数不仅可用于列表,也适用于元组、字符串、集合等。
nums = [23, 11, 32, 30, 17]
print(len(nums)) # 5
print(max(nums)) # 32
print(min(nums)) # 11
print(sum(nums)) # 113
# sorted 返回新列表,原列表不变
new_nums = sorted(nums, reverse=True)
print(new_nums) # [32, 30, 23, 17, 11]
print(nums) # [23, 11, 32, 30, 17]1.6 遍历列表的三种方式
scores = [62, 50, 60, 48, 80]
# while 循环
i = 0
while i < len(scores):
print(scores[i])
i += 1
# for 循环(最简洁)
for s in scores:
print(s)
# for + enumerate 同时获取索引和值
for idx, s in enumerate(scores, start=1):
print(f'第{idx}个成绩: {s}')1.7 小练习:成绩统计程序
需求:用户不断输入学生成绩,直到输入“结束”。随后统计总人数、最高分、最低分、平均分、合格率(≥60)和优秀率(≥90)。
print('请输入学生成绩,输入"结束"停止录入')
score_list = []
while True:
data = input('请输入成绩:')
if data == '结束':
break
else:
score_list.append(int(data))
if score_list:
avg = sum(score_list) / len(score_list)
pass_count = sum(1 for s in score_list if s >= 60)
excellent_count = sum(1 for s in score_list if s >= 90)
pass_rate = pass_count / len(score_list) * 100
excellent_rate = excellent_count / len(score_list) * 100
print('********⬇️统计信息如下⬇️********')
print(f'🧑🎓总人数:{len(score_list)}')
print(f'🔺最高分:{max(score_list)}')
print(f'🔻最低分:{min(score_list)}')
print(f'✅合格人数:{pass_count}人')
print(f'📈合格率:{pass_rate:.1f}%')
print(f'🏆优秀人数:{excellent_count}人')
print(f'📈优秀率:{excellent_rate:.1f}%')
print(f'📊平均分数:{avg:.1f}')
else:
print('您没有输入任何成绩!')2. 元组(tuple)—— 不可变的列表
元组与列表类似,也是有序存放一组数据,但一旦创建就不能修改(不能增、删、改,只能查)。这使它更安全,适合表示一组固定不变的结构化数据,例如坐标、RGB颜色值等。
2.1 定义元组
t1 = (28, 67, 21, 67, 11)
t2 = ('北京', 'Python', '你好')
t3 = (100, True, '你好', None)
t4 = (100, True, '你好', None, (50, 60, 70)) # 嵌套元组
empty = ()
also_empty = tuple()
# 单元素元组必须加逗号,否则括号会被当成普通括号
single = ('Python',)2.2 访问元素
元组同样支持正负索引,用法与列表完全一样。
data = (28, 67, 21, 67, 11)
print(data[0]) # 28
print(data[-1]) # 112.3 不可变 ≠ 内部不可变
虽然元组本身不能修改,但如果元组内包含了可变对象(如列表),这个可变对象的内容仍然可以改变。
t = (10, 20, [100, 200])
t[2][0] = 999
print(t) # (10, 20, [999, 200])2.4 常用方法与函数
由于不可修改,元组只有 index() 和 count() 两个方法。
t = (28, 67, 21, 67, 11)
print(t.index(67)) # 1
print(t.count(67)) # 2内置函数与列表通用:
nums = (23, 11, 32, 30, 17)
print(max(nums)) # 32
print(min(nums)) # 11
print(len(nums)) # 5
print(sum(nums)) # 113
print(sorted(nums)) # [11, 17, 23, 30, 32] (返回列表!)遍历元组同样用 for 循环。
2.5 解包——把元组/列表“拆开”
在函数调用时,可以用 * 将列表或元组解包,将其元素作为多个独立的参数传入。
def test(*args):
print('收到的参数:', args)
test(*[100, 200, 300]) # 相当于 test(100,200,300)
test(*('a', 'b', 'c')) # 相当于 test('a','b','c')3. 字符串(str)—— 字符的不可变序列
字符串也是数据容器,存放一组有序的字符,且不可修改。之前学过的字符串格式化、转义等知识不再重复,这里只从容器角度补充它的特性。
3.1 下标与不可变性
msg = 'welcome to python'
print(msg[3]) # 'c'
print(msg[-1]) # 'n'
# msg[0] = 'W' # ⛔ TypeError: 字符串不可修改3.2 常用方法
s = 'welcome to python'
# 查找
print(s.index('t')) # 8
# 分割
text = '北京@上海@广州'
print(text.split('@')) # ['北京', '上海', '广州']
# 替换(返回新字符串)
new_s = s.replace('python', 'Python')
print(new_s) # welcome to Python
# 计数
print(s.count('o')) # 3
# 去除两端字符
print('...Python...'.strip('.')) # Python3.3 遍历
for ch in 'Python':
print(ch)4. 序列的通用操作:切片与连接
列表、元组、字符串都被称为序列,因为它们有序、可下标访问。序列支持两个极具 Python 特色的通用操作:切片和相加/重复。
4.1 切片
语法:序列[起始:结束:步长],左闭右开区间(包含起始,不包含结束)。
lst = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
print(lst[0:5:1]) # [10,20,30,40,50] 从0到4,步长1
print(lst[1:8:2]) # [20,40,60,80] 从1到7,每隔一个取
print(lst[::]) # 完整拷贝
print(lst[3:]) # 从索引3到末尾
print(lst[:5]) # 从开头到索引4
print(lst[::-1]) # 步长为-1,实现逆序! [100,90,...,10]切片同样适用于元组和字符串,返回同类型容器。
4.2 序列相加与重复
相加:将两个同类型序列拼接成一个新序列。
重复:将序列重复指定次数。
# 相加
print([1,2] + [3,4]) # [1,2,3,4]
print(('a','b') + ('c','d')) # ('a','b','c','d')
print('Hello' + 'World') # 'HelloWorld'
# 重复
print([1,2] * 3) # [1,2,1,2,1,2]
print('Hi' * 3) # 'HiHiHi'5. 集合(set)—— 无序且唯一的元素
如果你只关心元素“是否存在”,而不在乎顺序,并且希望自动去重,那么集合是最佳选择。集合分为:
可变集合(set):可以增删元素。
不可变集合(frozenset):创建后不可修改,可放入另一个集合中。
5.1 定义集合
# 可变集合(自动去重,顺序不定)
s1 = {10, 20, 20, 30} # {10, 20, 30}
s2 = {'apple', 'banana', 'apple'}
# 空集合必须用 set() ({} 是空字典)
empty = set()
# 不可变集合
fs = frozenset([10, 20, 30])
# 集合中只能包含不可变类型(数字、字符串、元组)
valid = {10, 'Hi', (1,2)}
# invalid = {10, [1,2]} # ❌ 列表不可哈希5.2 增删改查
因为无序,集合没有下标,也没有“修改”这一说,但可以通过 remove + add 间接实现。
s = {10, 20, 30}
# 增
s.add(40)
s.update([50, 60], (70,)) # 批量添加
# 删
s.remove(20) # 元素不存在会报错
s.discard(999) # 不存在不报错
popped = s.pop() # 随机删除并返回一个元素
s.clear() # 清空
# 查:用成员运算符 in / not in
print(10 in s)5.3 集合的特殊方法(交、并、差)
A = {10, 20, 30, 40}
B = {30, 40, 50, 60}
# 差集:A 有而 B 没有的元素
print(A.difference(B)) # {10, 20}
# 直接修改A,去掉与B共有的部分
A.difference_update(B) # A 变为 {10, 20}
A = {10, 20, 30, 40}
# 并集:所有不重复元素
print(A.union(B)) # {10,20,30,40,50,60}
# 子集与超集
C = {30, 40}
print(C.issubset(A)) # True
print(A.issuperset(C)) # True
# 是否有交集?(无交集返回 True)
print({10,20}.isdisjoint({30,40})) # True5.4 数学运算符
集合还支持运算符,写法更直观:
s1 = {10, 20, 30, 40}
s2 = {30, 40, 50, 60}
print(s1 | s2) # 并集
print(s1 & s2) # 交集
print(s1 - s2) # 差集
print(s1 ^ s2) # 对称差集(并集减去交集)5.5 遍历集合
集合只能用 for 循环遍历,因为它没有下标。
for item in {10, 20, 30}:
print(item)6. 字典(dict)—— 键值对的映射容器
字典通过唯一的键(key)来快速查找对应的值(value),就像一本电话簿:名字→号码。这使得它在需要建立映射关系的场景下无可替代。
6.1 定义字典
d1 = {'张三': 72, '李四': 60, '王五': 85}
# 键不能重复,重复时后者覆盖前者
d2 = {'A': 1, 'B': 2, 'A': 99} # 最终 'A': 99
# 空字典
d3 = {}
d4 = dict()
# 键必须是不可变类型,值任意
d5 = {100: '分数', 'name': '张三', (1,2): '坐标'}
# 嵌套:学生管理系统常用结构
students = {
2024001: {'姓名': '张三', '成绩': 72, '爱好': ['阅读', '编程']},
2024002: {'姓名': '李四', '成绩': 60, '爱好': ['篮球', '音乐']}
}6.2 增删改查
d = {'张三':72, '李四':60}
# 增 / 改(写法相同,键存在则改,不存在则增)
d['王五'] = 85 # 新增
d['张三'] = 99 # 修改
d.update({'李四':40, '赵六':100}) # 批量更新
# 删
del d['张三'] # 删除指定键值对
value = d.pop('李四') # 删除并返回值
result = d.pop('奥特曼', '不存在') # 安全弹出(可设默认值)
d.clear() # 清空
# 查
print(d['王五']) # 直接取值,键不存在会报错
print(d.get('奥特曼', '默认值')) # 安全取值,无键时返回默认值6.3 键、值、键值对的视图
keys(), values(), items() 返回可遍历的视图对象,可轻松配合循环使用。
d = {'张三':72, '李四':60}
print(d.keys()) # dict_keys(['张三', '李四'])
print(d.values()) # dict_values([72, 60])
print(d.items()) # dict_items([('张三', 72), ('李四', 60)])
# 遍历方式
for name in d:
print(f'{name}: {d[name]}')
for name, score in d.items():
print(f'{name} -> {score}')7. 数据容器的通用操作
7.1 类型转换函数
Python 提供了 list(), tuple(), set(), str(), dict() 等函数,它们既可以创建空容器,也能将其他可迭代对象转换成对应类型。
print(list(range(5))) # [0,1,2,3,4]
print(tuple('abc')) # ('a','b','c')
print(set([1,2,2,3])) # {1,2,3} 自动去重
print(str(123)) # '123'
# 字典转换需要提供键值对
print(dict([('a',1), ('b',2)])) # {'a':1, 'b':2}7.2 成员运算符 in 和 not in
所有容器都支持 in / not in,用来判断某个元素是否存在。对于字典,它判断的是键是否存在。
hobby = ['阅读', '编程', '音乐']
print('编程' in hobby) # True
citys = {'北京', '上海', '广州'}
print('上海' not in citys) # False
scores = {'张三':75, '李四':60}
print('李四' in scores) # True(检查键)
print(75 in scores.values()) # True(检查值)8. 综合案例:简易学生信息管理系统
把字典、列表、循环、条件判断综合起来,实现一个命令行版的学生管理程序:支持添加、删除、修改成绩、查询和统计。
students = {}
while True:
print('\n=== 学生管理 ===')
print('1.添加 2.删除 3.修改 4.查询 5.显示全部 6.统计 0.退出')
op = input('选择: ')
if op == '1':
name = input('姓名: ')
score = int(input('成绩: '))
students[name] = score
print('已添加')
elif op == '2':
name = input('删除谁: ')
if name in students:
del students[name]
print('已删除')
else:
print('不存在')
elif op == '3':
name = input('姓名: ')
if name in students:
new_score = int(input('新成绩: '))
students[name] = new_score
print('已更新')
else:
print('不存在')
elif op == '4':
name = input('查询: ')
print(students.get(name, '未找到'))
elif op == '5':
for n, s in students.items():
print(f'{n}: {s}')
elif op == '6':
if students:
scores = list(students.values())
avg = sum(scores) / len(scores)
print(f'人数:{len(scores)} 最高:{max(scores)} 最低:{min(scores)} 平均:{avg:.1f}')
print(f'合格率:{sum(1 for s in scores if s>=60)/len(scores)*100:.1f}%')
else:
print('无数据')
elif op == '0':
break
else:
print('无效输入')9. 一张表总结五大容器特性
选型建议:
需要顺序且要增删改查 → 列表
数据固定不变 → 元组
处理文本 → 字符串
去重、集合运算 → 集合
键值对映射 → 字典
掌握了这五种数据容器,你就拥有了处理绝大多数数据场景的能力。配合内置函数和强大的序列操作,Python 的数据管理会变得异常轻松。希望这篇博客能帮你建立起清晰的容器知识体系,并在实际编程中灵活运用它们。