前面这一整阶段,我们已经把列表、元组、字典、集合分别学过了。
如果只看单个知识点,你可能会觉得自己已经会了。 列表会增删改查,字典也能遍历,集合知道能去重,元组知道不可变。 但很多人一到自己写程序,还是会发懵。
因为真正难的,从来不是把一个知识点背下来。 真正难的是,面对一个具体需求时,你能不能把这些容器一起用起来。
这一章,我们就不再单独讲某一种容器。 我们来做几个更接近真实使用场景的小案例,把前面的知识真正串起来。
你会慢慢发现:
知识点一个一个学的时候,像零件 可一旦组合起来,才真正开始像工具
一、为什么一定要做综合练习
很多新手有一个常见误区。
觉得自己看懂了,就等于会用了。
其实差得远。
你看懂 append(),不代表你会组织一份学生名单。 你知道 dict.get(),不代表你会写一个信息管理程序。 你学过 set() 去重,也不代表你拿到一堆脏数据时,第一反应就知道该怎么处理。
所以综合练习的价值,不是再多教几个新语法。 而是让你把前面学过的东西,真正放进一个完整的小问题里去用。
这一步很重要。 很多人从 会听 走向 会写,靠的就是这种练习。
二、先记住一个原则:不要一上来就写代码
以后你做题、做项目、做练习,先别急着敲。
先想三件事:
我手里的数据长什么样 适合放进哪种容器 我要对这些数据做什么操作
比如学生信息,通常适合字典。 很多个学生,就往往是列表套字典。 如果有重复姓名要去重,集合就可能要出场。 如果某个信息是固定搭配,比如坐标、日期,也许元组更合适。
你会发现,很多问题只要容器选对了一半,后面写起来就顺了。
三、案例一:做一个简单的学生成绩管理器
这个案例非常适合入门阶段。 因为它几乎能把前面学过的容器都串起来。
需求很简单:
保存多个学生的信息 每个学生有 姓名、年龄、成绩 打印所有学生信息 找出成绩最高的学生 统计有没有重名
先想数据结构。
多个学生,适合列表。 每个学生有多个字段,适合字典。
所以整体结构可以这样设计:
students = [ {'name': '张三', 'age': 18, 'score': 95}, {'name': '李四', 'age': 19, 'score': 88}, {'name': '王五', 'age': 17, 'score': 92}, {'name': '张三', 'age': 18, 'score': 90}]
你先别急着嫌这个例子简单。 真实开发里,很多数据本质上就是这个样子。
外层一堆记录 内层每条记录是一组字段
四、先把所有学生信息打印出来
这是最基础的一步。
students = [ {'name': '张三', 'age': 18, 'score': 95}, {'name': '李四', 'age': 19, 'score': 88}, {'name': '王五', 'age': 17, 'score': 92}, {'name': '张三', 'age': 18, 'score': 90}]for student in students: print('姓名:', student['name'], '年龄:', student['age'], '成绩:', student['score'])
这段代码不复杂,但它非常典型。
列表负责装很多条记录。 字典负责描述每条记录的字段。 循环负责把它们一条条取出来。
学编程其实就是这样。 不是每一步都难,而是很多简单步骤组合起来,开始解决一个完整问题。
五、找出成绩最高的学生
这个需求也非常常见。
先准备一个变量,默认把第一个学生当成最高分:
students = [ {'name': '张三', 'age': 18, 'score': 95}, {'name': '李四', 'age': 19, 'score': 88}, {'name': '王五', 'age': 17, 'score': 92}, {'name': '张三', 'age': 18, 'score': 90}]top_student = students[0]for student in students:if student['score'] > top_student['score']: top_student = studentprint('最高分学生是:', top_student)
输出结果会是:
最高分学生是: {'name': '张三', 'age': 18, 'score': 95}
这里你会更直观地体会到字典的好处。
如果每个学生用列表来表示,你就得记住哪个位置是成绩。 而现在直接写 student['score'],意思非常清楚。
这就是为什么说,数据结构不是形式主义。 它直接决定了你后面写代码顺不顺手。
六、统计有没有重名,用集合就很舒服
现在有个新需求:
看看学生名单里有没有重复姓名。
如果硬用列表一点点比,当然也能做。 但既然前面学过集合,完全可以更自然一点。
students = [ {'name': '张三', 'age': 18, 'score': 95}, {'name': '李四', 'age': 19, 'score': 88}, {'name': '王五', 'age': 17, 'score': 92}, {'name': '张三', 'age': 18, 'score': 90}]name_list = []for student in students: name_list.append(student['name'])name_set = set(name_list)print('原名单人数:', len(name_list))print('去重后人数:', len(name_set))
如果两个数量不一样,就说明有重名。
再写得直白一点:
if len(name_list) != len(name_set): print('存在重名学生')else: print('没有重名学生')
你看,集合一进来,问题立刻清爽很多。
这也是你以后写代码时要培养的反射:
一旦脑子里出现 去重、重复、有没有相同值 就要想到 set
七、把这个案例再推进一步
我们再做一个稍微完整一点的输出。
比如打印所有学生,同时标出最高分是谁:
students = [ {'name': '张三', 'age': 18, 'score': 95}, {'name': '李四', 'age': 19, 'score': 88}, {'name': '王五', 'age': 17, 'score': 92}, {'name': '张三', 'age': 18, 'score': 90}]top_student = students[0]for student in students:if student['score'] > top_student['score']: top_student = studentfor student in students: print(student)print('最高分是:', top_student['name'], top_student['score'])
到这里为止,这已经不是零散知识点了,而是一个能跑通的小功能。
虽然简单,但这就是编程真正的样子。 你不是在背概念,而是在组织数据、处理数据、输出结果。
八、案例二:做一个商品标签清洗器
这个案例特别接近真实业务。
假设你运营一个商品库,每个商品都有很多标签。 但这些标签很乱,有重复,有顺序问题,还有一些你想统一处理。
比如:
tags = ['键盘', '机械键盘', '办公', '键盘', '数码', '办公', '外设']
现在我们想做三件事:
先去重 再转成列表 最后按字母或规则排序展示
先去重:
tags = ['键盘', '机械键盘', '办公', '键盘', '数码', '办公', '外设']tag_set = set(tags)print(tag_set)
这一步的重点不是输出长什么样,而是重复标签已经没了。
接着转回列表:
tag_list = list(tag_set)print(tag_list)
如果你还想排序:
tag_list.sort()print(tag_list)
把这几步合在一起看:
tags = ['键盘', '机械键盘', '办公', '键盘', '数码', '办公', '外设']tag_list = list(set(tags))tag_list.sort()print('清洗后的标签列表:', tag_list)
这个过程特别值得你记住。
原始列表 转集合去重 再转列表继续处理
这就是典型的数据清洗思路。
很多人觉得数据处理很高深,其实一开始真没那么玄。 很多时候,就是在不同容器之间来回转换。
九、为什么这个案例很有代表性
因为现实里的很多数据,本来就不整洁。
比如:
文章标签重复 商品分类混乱 用户名单有重复 日志编号重复 爬虫抓下来的链接一堆重复值
这些问题,单看都不难。 但如果你没有容器切换的意识,就会写得又绕又笨。
而一旦你熟悉了:
列表适合装原始数据 集合适合去重 再转回列表方便排序和展示
很多数据清洗场景都会一下子变简单。
十、案例三:做一个联系人信息表
这一类问题,更适合用字典。
假设现在要保存几个人的联系方式。
我们可以这样设计:
contacts = {'张三': '13800000001','李四': '13800000002','王五': '13800000003'}
这个结构一眼就很像通讯录。 名字是键,手机号是值。
现在我们来做几个最常见的小操作。
先查某个人的号码:
print(contacts['张三'])
再新增一个联系人:
contacts['赵六'] = '13800000004'print(contacts)
再修改一个号码:
contacts['李四'] = '13999999999'print(contacts)
再遍历所有联系人:
for name, phone in contacts.items(): print(name, phone)
这个案例虽然基础,但特别重要。 因为它开始让你意识到:
不是所有数据都该装进列表里 一旦数据本身是 名称 对应 内容 字典就会比列表自然太多
十一、再给联系人加一个更像项目的结构
如果每个人不只是手机号,还有城市和年龄呢?
这时候就不能只让值是一个字符串了。 可以把值也设计成字典。
contacts = {'张三': {'phone': '13800000001', 'city': '北京', 'age': 20},'李四': {'phone': '13800000002', 'city': '上海', 'age': 22},'王五': {'phone': '13800000003', 'city': '深圳', 'age': 19}}
现在如果你想取李四的城市:
print(contacts['李四']['city'])
如果你想遍历所有联系人并打印详细信息:
for name, info in contacts.items(): print(name, info['phone'], info['city'], info['age'])
这就开始有一点真实项目的味道了。
外层字典表示很多联系人 内层字典表示每个人的详细属性
你以后写用户信息、商品信息、订单信息,结构往往也很像这样。
十二、案例四:固定坐标信息,元组为什么合适
前面几个案例里,元组存在感好像不强。 现在我们专门给它一个适合的场景。
假设你要保存几个点的坐标:
points = [(0, 0), (1, 2), (3, 4), (5, 6)]
这里外层为什么用列表?
因为有很多个点,而且后面可能还会继续增加。
内层为什么用元组?
因为每个坐标本身就是一组固定搭配的值。 你不太希望它被当成普通列表那样随便 append、remove。
接着遍历这些点:
points = [(0, 0), (1, 2), (3, 4), (5, 6)]for point in points: x, y = point print('x =', x, 'y =', y)
这里还顺手用到了元组拆包。
这就是元组最舒服的地方。 它不一定每天都高频出现,但只要遇到 固定小组合,往往就很顺手。
比如:
坐标 日期 RGB 颜色值 宽和高 年月日时分秒
这些都很适合元组。
十三、案例五:做一个简单的签到统计
再来看一个把列表、集合、字典放在一起的小案例。
假设今天有这么一份签到名单:
checkins = ['张三', '李四', '王五', '张三', '赵六', '李四']
我们想做三件事:
去重 统计实际签到人数 给每个人生成一个签到状态表
先去重:
checkin_set = set(checkins)print(checkin_set)
再统计人数:
print('实际签到人数:', len(checkin_set))
最后生成签到状态表:
status = {}for name in checkin_set: status[name] = '已签到'print(status)
完整代码:
checkins = ['张三', '李四', '王五', '张三', '赵六', '李四']checkin_set = set(checkins)status = {}for name in checkin_set: status[name] = '已签到'print('签到名单去重后:', checkin_set)print('实际签到人数:', len(checkin_set))print('签到状态表:', status)
这个小例子就很有意思。
原始数据来自列表 去重靠集合 最终展示状态靠字典
这就是综合练习的价值。 你开始看到,容器不是孤零零存在的,而是会互相配合。
十四、把这几个案例放在一起,你就会发现一条主线
学生成绩管理器里,核心是 列表套字典。 商品标签清洗器里,核心是 列表转集合再转回列表。 联系人信息表里,核心是 字典套字典。 坐标列表里,核心是 列表套元组。 签到统计里,核心是 列表、集合、字典联动。
它们看起来像五个例子,实际上都在训练同一件事:
根据数据的特点,选合适的容器 根据任务的变化,做合适的转换 再用循环和判断把逻辑串起来
这才是真正的编程基础能力。
十五、综合练习时最容易犯的几个错
先说第一个。
一股脑把所有东西都塞进列表。
这是新手最常见的问题。 因为列表最早学,也最顺手,所以什么都想往里面扔。 但一旦数据开始带字段、有去重需求、有固定组合,列表就不一定是最佳选择了。
第二个错,是字典字段名乱写。
比如前面写的是 score,后面却写成 scroe。 这种错特别常见,而且程序还会直接报错。 所以字段名一定要保持一致。
第三个错,是明明需要去重,还一直硬用列表判断。 能用集合解决的问题,就别把逻辑写得太绕。
第四个错,是顺序意识不清。
集合去重虽然方便,但顺序往往会丢。 所以如果业务特别依赖原顺序,就别一上来就直接 set()。
第五个错,是例子看懂了,自己不敲。 这真的是很多人停滞不前的根源。
你不自己敲一遍,知识永远只停留在眼睛里。 真正的熟悉感,是手敲出来的。
十六、怎么把这些小案例练成自己的能力
这里给你一个特别实用的方法。
不要只复制运行。 你可以在每个案例的基础上,自己给它加一点变化。
比如学生成绩案例里,你可以加一个求平均分。 联系人案例里,你可以加一个判断某个联系人在不在。 标签案例里,你可以试试按标签长度排序。 签到案例里,你可以加一个未签到名单对比。
你会发现,一旦开始改,很多知识点就会真正活起来。
编程水平很多时候不是学来的,而是改出来的。 你越改,越会感觉这些容器开始听使唤,而不是只存在教程里。
十七、给你一组很适合练手的小任务
下面这些题,你可以在今天或者明天自己练。
第一个,做一个图书列表。 每本书包含 书名、作者、价格。 要求打印所有图书,并找出最贵的一本。
第二个,做一个用户注册名单去重。 原始用户名放在列表里,最后输出不重复用户名数量。
第三个,做一个商品信息表。 用字典保存商品名、价格、库存,再遍历输出。
第四个,保存几个日期数据。 每个日期用元组表示 年、月、日,然后放进列表里统一打印。
第五个,做一个课程签到表。 原始签到名单用列表,去重后转成字典,值统一设为 已到。
这些题都不复杂,但特别适合把这一阶段的内容真正打通。
十八、你应该开始形成的思维,不是写代码,而是组织数据
这一章最重要的,不是哪一行代码有多酷。 而是你要慢慢意识到:
程序很多时候不是在写语法 而是在组织数据
学生信息怎么存 商品标签怎么清洗 联系人怎么表达 签到名单怎么统计 坐标怎么表示
这些问题,表面上在写 Python。 本质上是在训练你怎么把现实问题,翻译成合适的数据结构。
这一步一旦建立起来,你后面学字符串、函数、文件、项目开发,都会顺很多。
因为你不再只是会写某个语句。 你开始能把一堆数据放进合理的结构里了。
十九、本章小结
这一章我们没有学新语法,但它非常重要。
因为从这一章开始,前面学过的列表、元组、字典、集合,终于不再是分散的知识点,而开始变成能配合使用的工具。
你要记住这几个核心体会:
多个同类对象,常常用列表来装。 一条对象信息,常常用字典来描述。 固定搭配的小组合,往往适合元组。 去重和成员判断,集合非常高效。 真实问题里,它们常常是组合使用,而不是单独出场。
如果你现在已经能看懂这些小案例,那说明你已经不只是会一点语法了。 你开始真正接触到 编程是怎么把现实问题变成程序问题 的过程了。
下一章我们就进入第五阶段,开始系统学习字符串专题。 那里会是另一个高频重灾区。 因为几乎所有真实项目,最后都绕不开文本处理。