06数据容器

06数据容器

_

注:学习资料来源<尚硅谷>

视频:点击跳转

代码仓库: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的出现次数,输出 2

1.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])  # 11

2.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('.'))   # Python

3.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}))  # True

5.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 成员运算符 innot 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. 一张表总结五大容器特性

容器

有序

可变

元素可重复

访问方式

典型写法

列表 list

下标 [i]

[1,2,3]

元组 tuple

下标 [i]

(1,2,3)

字符串 str

下标 [i]

"hello"

集合 set

成员运算 in

{1,2,3}

字典 dict

键唯一

[key]

{'a':1, 'b':2}

选型建议:

  • 需要顺序且要增删改查 → 列表

  • 数据固定不变 → 元组

  • 处理文本 → 字符串

  • 去重、集合运算 → 集合

  • 键值对映射 → 字典


掌握了这五种数据容器,你就拥有了处理绝大多数数据场景的能力。配合内置函数和强大的序列操作,Python 的数据管理会变得异常轻松。希望这篇博客能帮你建立起清晰的容器知识体系,并在实际编程中灵活运用它们。

05函数入门 2026-04-24

评论区