Python 数据容器详解,list、tuple、str、set、dict 到底怎么选
变量能保存一个值。
但程序真正开始有用,往往是从处理一批数据开始的。
学生名单、商品列表、电影信息、订单记录、接口返回的 JSON,这些都不是一个变量能优雅解决的。
Python 提供了几种非常常用的数据容器:
list、tuple、str、set、dict
很多初学者的问题不是不会写语法,而是不知道什么时候该用谁。
这篇文章就把它们一次讲清楚。
先看一个真实一点的数据结构
假设我们要表示一部电影:
movie = {
"title": "流浪地球",
"year": 2019,
"score": 7.9,
"tags": ["科幻", "冒险", "灾难"],
"directors": ("郭帆",)
}
print(movie["title"])
print(movie["tags"][0])
这里同时用了字典、列表和元组。
字典描述一部电影的多个属性。
列表保存多个标签。
元组保存不太需要修改的导演信息。
真实项目里的数据经常就是这样嵌套的。
list,最常用的列表
列表有顺序,可以修改,适合保存一组同类数据。
students = ["小明", "小红", "小刚"]
print(students[0])
print(students[1])
索引从 0 开始。
常用操作:
students = ["小明", "小红"]
students.append("小刚")
students.insert(1, "小李")
students.remove("小红")
print(students)
print(len(students))
append() 加到末尾。
insert() 插入指定位置。
remove() 按值删除。
len() 获取长度。
列表切片
切片格式:
items[start:end:step]
示例:
numbers = [10, 20, 30, 40, 50]
print(numbers[1:4])
print(numbers[:3])
print(numbers[2:])
print(numbers[::2])
输出:
[20, 30, 40]
[10, 20, 30]
[30, 40, 50]
[10, 30, 50]
规则是包含开始位置,不包含结束位置。
这个规则刚开始有点别扭,但非常统一。range() 也是不包含结束值。
列表遍历
只需要元素:
scores = [90, 85, 72]
for score in scores:
print(score)
同时需要索引和元素:
scores = [90, 85, 72]
for index, score in enumerate(scores):
print(index, score)
不要为了拿索引强行写:
scores = [90, 85, 72]
for index in range(len(scores)):
print(scores[index])
这不是错,但如果你不需要索引,直接遍历元素更清楚。
tuple,固定结构的数据
元组有顺序,但创建后不能修改。
point = (120.1, 30.2)
print(point[0])
print(point[1])
元组适合保存结构固定的数据,比如坐标、日期片段、函数多个返回值。
def get_min_max(numbers):
return min(numbers), max(numbers)
min_value, max_value = get_min_max([3, 8, 1, 9])
print(min_value)
print(max_value)
这里函数返回了两个值。Python 实际上返回的是一个元组,只是我们可以很方便地拆开。
str,字符串也是序列
字符串是文本,也是一种不可变序列。
word = "Python"
print(word[0])
print(word[1:4])
字符串常用方法:
text = " Python,AI,Web "
print(text.strip())
print(text.lower())
print(text.replace("AI", "Data"))
print(text.split(","))
strip() 去掉两端空白。
lower() 转小写。
replace() 替换文本。
split() 按分隔符切分成列表。
字符串不能直接修改某个字符:
word = "Python"
# word[0] = "J" 这行会报错
要生成新字符串:
word = "Python"
new_word = "J" + word[1:]
print(new_word)
set,去重和集合运算
集合不保存重复元素。
tags = {"Python", "AI", "Python", "Web"}
print(tags)
集合适合做去重:
names = ["小明", "小红", "小明", "小刚"]
unique_names = set(names)
print(unique_names)
集合运算:
frontend = {"HTML", "CSS", "JavaScript", "Python"}
backend = {"Python", "Java", "Go"}
print(frontend & backend)
print(frontend | backend)
print(frontend - backend)
& 是交集。
| 是并集。
- 是差集。
集合不适合用索引,因为它不强调顺序。
dict,用键找到值
字典保存键值对。
user = {
"name": "小明",
"age": 18,
"is_vip": True
}
print(user["name"])
修改和新增:
user = {"name": "小明", "age": 18}
user["age"] = 19
user["city"] = "杭州"
print(user)
安全读取:
user = {"name": "小明"}
print(user.get("age", "未知"))
如果直接 user["age"],键不存在会报 KeyError。
get() 可以给默认值。
字典遍历
遍历键:
user = {"name": "小明", "age": 18}
for key in user:
print(key)
遍历值:
for value in user.values():
print(value)
遍历键和值:
for key, value in user.items():
print(key, value)
真实开发里,items() 很常用。
容器怎么选
可以按这个流程判断:
简单判断:
保存多个学生,用列表。
描述一个学生,用字典。
保存坐标,用元组。
处理标签去重,用集合。
处理文本,用字符串。
可变和不可变
列表、字典、集合是可变的。
字符串、元组、数字是不可变的。
看列表:
items = [1, 2, 3]
items.append(4)
print(items)
原列表被修改了。
看字符串:
name = "Python"
new_name = name.replace("P", "J")
print(name)
print(new_name)
原字符串没有变,生成了新字符串。
这个区别会影响函数参数、复制、数据共享。现在先记住规则,后面写项目时会经常遇到。
浅拷贝的入门坑
numbers = [1, 2, 3]
other_numbers = numbers
other_numbers.append(4)
print(numbers)
输出:
[1, 2, 3, 4]
因为 numbers 和 other_numbers 指向同一个列表。
如果想复制一份:
numbers = [1, 2, 3]
other_numbers = numbers.copy()
other_numbers.append(4)
print(numbers)
print(other_numbers)
这只是浅拷贝。嵌套结构会更复杂,入门阶段先知道不要随便把可变对象赋来赋去。
完整案例,学生成绩统计
students = [
{"name": "小明", "score": 90, "tags": {"认真", "稳定"}},
{"name": "小红", "score": 85, "tags": {"活跃", "进步"}},
{"name": "小刚", "score": 72, "tags": {"稳定"}},
]
total_score = 0
passed_students = []
all_tags = set()
for student in students:
total_score = total_score + student["score"]
if student["score"] >= 60:
passed_students.append(student["name"])
all_tags = all_tags | student["tags"]
average_score = total_score / len(students)
print(f"平均分:{average_score:.2f}")
print(f"及格学生:{passed_students}")
print(f"所有标签:{all_tags}")
这个例子里:
列表保存多个学生。
字典描述单个学生。
集合保存标签并自动去重。
循环负责逐个处理。
这就是容器组合的真实用法。
常见错误
索引越界
names = ["小明", "小红"]
print(names[2])
列表只有索引 0 和 1,访问 2 会报 IndexError。
字典键不存在
user = {"name": "小明"}
print(user["age"])
会报 KeyError。
修复:
print(user.get("age", "未知"))
修改正在遍历的列表
numbers = [1, 2, 3, 4]
for number in numbers:
if number % 2 == 0:
numbers.remove(number)
这类代码容易跳过元素。
更安全的方式是生成新列表:
numbers = [1, 2, 3, 4]
odd_numbers = []
for number in numbers:
if number % 2 != 0:
odd_numbers.append(number)
print(odd_numbers)
练习
写一个图书统计程序:
- 用列表保存多本书。
- 每本书用字典表示,包含书名、价格、标签。
- 统计所有书的平均价格。
- 汇总所有标签并去重。
参考代码:
books = [
{"title": "Python 入门", "price": 59.9, "tags": {"编程", "Python"}},
{"title": "数据分析基础", "price": 69.0, "tags": {"数据", "Python"}},
{"title": "Web 开发", "price": 79.0, "tags": {"Web", "Python"}},
]
total_price = 0
all_tags = set()
for book in books:
total_price = total_price + book["price"]
all_tags = all_tags | book["tags"]
average_price = total_price / len(books)
print(f"平均价格:{average_price:.2f}")
print(f"全部标签:{all_tags}")
参考资料
- Python 官方数据结构教程:https://docs.python.org/3/tutorial/datastructures.html
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)