第26章-知识点串讲与项目需求分析


前五周你学了一身零散的招式:变量、循环、函数、文件、类。每一招单独拿出来都会用,但还没把它们合起来做过一件完整的作品——就像学了十种刀工,还没上灶炒过一整桌菜。

这周不一样了。本周要做你的第一个完整项目:通讯录或者记账本,二选一,全程可以用 AI 辅助。今天不写代码,任务是开工前的"图纸阶段":把前五周的知识盘一遍,读懂需求,定下数据结构,画出菜单流程图。图纸画清楚了,后面四天写代码就是照着施工;图纸是糊涂的,写着写着就得推倒重来。磨刀不误砍柴工,今天这把刀磨好了,后面轻松很多。顺便说一句,这种"先想清楚再动手"的节奏,也是 AI 编程时代的正确姿势——需求没想明白就让 AI 写代码,它只会把你脑子里的糊涂,放大成更大的糊涂。

先盘一盘:前五周学了什么

把工具箱里的工具全倒出来,挨个看看每把工具在"通讯录项目"里能拧哪个螺丝。先给你一句话定心:项目不引入新知识点,它只是把旧知识按顺序组装起来。所以这周不会有"听不懂的新东西",只有"用不熟的老东西"。

周次 模块 关键知识点 本项目里用在哪
第1周 环境与工具 文件管理、Git 提交、用 AI 写代码 建项目文件夹、周五提交 Git、全程 AI 辅助
第2周 变量与类型 int / float / str / bool、f-string 存姓名、电话、金额;打印格式化信息
第2周 流程控制 if / for / while / break 菜单选择、循环菜单、退出循环
第3周 数据结构 列表、字典、遍历 联系人列表;每条记录用一个字典
第4周 函数与文件 def、参数、return、open、json 每个功能一个函数;数据永久保存
第4周 异常处理 try / except 输入非法数字、文件不存在不崩溃
第5周 面向对象 类、对象(了解) 项目可用可不用,会用加分
第5周 AI 提问 四要素、三步法、追问 全程 AI 辅助开发

串起来记一句话:类型装数据、流程控顺序、结构管存储、函数拆功能、文件保数据、异常防崩溃、AI 提效率

看完这张表,有三件事得提前给你打预防针。第一,别指望项目周学新东西——它唯一的目的就是把旧知识用熟,用到哪卡住了再回头补。第二,面向对象只是"了解"级别,能用函数把项目写完就很棒,硬套类反而容易把自己绕晕。第三,第一周学的最容易忘:每天写完代码记得 Git 提交一次,这是职业习惯,周五验收要看提交记录的。

这份对照表周五还要用一次:答辩讲到"每个知识点用在哪"的时候,它就是现成的提纲。今天先混个脸熟。

什么是项目:从练习到作品

练习和项目的区别,你肯定有感觉。练习是"算一道数学题",做对就完;项目是"装修一套房子",得先看户型、再画设计图、然后施工、最后验收。项目(Project)= 一个能解决真实问题的完整程序

专业程序员的开发流程是固定的五步,以后每做一个项目都按这个来:

步骤 干的事 本周的对应动作
① 需求分析 搞清楚"要做什么功能" 读懂需求说明书
② 设计 想清楚"数据怎么存、流程怎么走" 设计数据结构 + 画流程图
③ 编码 把设计翻译成代码 周二到周四
④ 测试 跑一遍看有没有 bug 每天按"完成标准"自查
⑤ 完善与交付 加加分项、准备演示 周五

这条线就是本周五天的日程表:今天干①和②,周二到周四干③和④,周五干⑤。

新手最常见的死法,是拿到题目直接写代码,写到一半发现数据结构设计错了,全盘推翻重来。先想清楚再动手,能省一半时间。"需求分析"也不是走形式——功能清单里每一条,最后都要对应到代码里的一个函数,漏一条就是漏一个功能。

读懂需求说明书

需求说明书(Requirements)= 甲方告诉你要做什么的文字。这周的"甲方"是老师,需求已经替你写好了,你的活儿是把每条需求"翻译"成代码里的函数。

通讯录版的功能清单(官方需求):

编号 功能 说明 对应代码函数
1 添加联系人 输入姓名、电话(可选:备注),保存 add_contact
2 查看全部 分条显示,带编号 show_contacts
3 搜索联系人 按姓名或电话模糊搜索 search_contact
4 删除联系人 按编号删除 delete_contact
5 修改联系人 按编号修改电话(进阶) edit_contact
6 数据持久化 退出程序后数据还在(JSON 文件) load / save

读任何一条需求,都问自己三个问题:

  1. 用户要输入什么?(比如添加功能:姓名、电话)
  2. 程序要输出什么?(添加成功?还是联系人列表?)
  3. 数据要不要保存?(要 → 写文件;不要 → 只存内存)

任何需求都逃不出这三个问题,把它们想清楚,写代码就是顺水推舟的事。

读需求别当表扫,一条一条过。六条功能读完,你会发现它们其实是两拨:一拨"改数据"(添加、删除、修改),一拨"看数据"(查看、搜索),最后再加一个"持久化"收尾。这个分类现在先留个印象,后面四天你会反复用到它。

有两个词得先抠清楚。一是"模糊搜索":不是让你精确匹配"张三"两个字,而是输入一个"张",能把"张三""张伟"全搜出来——这决定了搜索要用 in 判断而不是 ==,明天细讲。二是"可选"功能(比如备注):第一天可以不做,先把主流程跑通,这正是"先跑通再完善"的意思。

数据结构:为什么是"列表套字典"

数据结构(Data Structure)= 数据在程序里怎么摆放。摆得合理,后面所有功能都简单;摆得乱,越写越痛苦。这是今天最重要的一节,多花五分钟想明白,后面四天都受益。

设计思路拆成两句话:

  • 一个联系人 = 一个字典,就像一张名片卡,姓名、电话是卡片上的栏目
  • 所有联系人 = 字典列表,就像一沓名片按顺序排好,也可以想象成一张 Excel 表格
# 一个联系人 = 一个字典(一张名片)
contact = {"name": "小明", "phone": "13800000000", "remark": "大学同学"}

# 所有联系人 = 字典列表(一沓名片)
contacts = [
    {"name": "小明", "phone": "13800000000"},
    {"name": "小红", "phone": "13900000000"},
]

# 取某个字段:先取行、再取列
print(contacts[0]["name"])   # 输出:小明
print(contacts[1]["phone"])  # 输出:13900000000

为什么非得是"列表套字典",而不是别的摆法?对比一下就清楚了:

方案 问题
用 3 个独立列表 name=[]、phone=[] 删一个人要同时删 3 个列表,下标错一位就全乱
用一个大字典 联系人顺序会乱,也没法方便地"按编号删除"
列表套字典 一行一个联系人,增删改查都围绕"一行"操作,最直观

记账本版本结构完全一样,只是字段不同:

# 一条账目 = 一个字典
record = {"type": "收入", "amount": 100, "note": "工资"}

# 所有账目 = 字典列表
records = [
    {"type": "收入", "amount": 100, "note": "工资"},
    {"type": "支出", "amount": 30, "note": "午饭"},
]

通讯录和记账本的开发流程 100% 一样,区别只是"卡片上的栏目"不同,选哪个都行,选你想做的那个。

怎么验证这个设计够不够用?拿"按编号删除"这个需求试一遍:显示编号需要按顺序遍历——列表能做;用户报编号后删掉对应的人——列表按下标删,没问题。设计能不能撑住需求,就靠这种"拿需求过一遍"的检查,比闷头想半天管用。

写数据结构时有三个坑,今天就得避开。第一,字典的键名全项目统一,写 "name" 就到处都用 "name",别一会 "name" 一会 "姓名"——键名写错(KeyError)是新手高频报错。第二,列表里的元素是字典不是字符串,取字段必须 c["name"] 这种"先取行、再取列"的写法。第三,设计时就要想到"删除"——既然要按编号删除,数据就必须是有顺序的列表,不能用集合(set 没有顺序、没有下标)。

把菜单画成流程图

流程图(Flowchart)= 用箭头把程序的运行顺序画出来。写字楼里贴的消防疏散图就是流程图,照着走就知道下一步去哪。程序也一样,先画图再写码,脑子特别清楚。

今天必须画出通讯录的菜单流程图,照这张图,明天就能写出主循环:

        ┌─────────────┐
          打开程序            └──────┬──────┘
                       ┌─────────────┐
          显示菜单        1.添加 2.查看 3.搜索 4.删除 5.退出
        └──────┬──────┘
                       ┌─────────────┐
          等待输入            └──────┬──────┘
                  ┌───────────┴───────────┐
    按数字分支(if/elif     └───┬────┬────┬────┬────┘
                            添加  查看  搜索  删除  退出
                              └────┴────┴────┘                                      ┌─────────┐                 回到菜单 │◄───────┘    这是关键:执行完功能要"绕回来"
        └─────────┘          再显示一次菜单,直到用户选退出

图里最关键的是"回到菜单"那条回环线——它翻译成代码就是一个 while True 循环:程序永远重复"显示菜单 → 选择 → 执行",只有用户选"退出"时才用 break 跳出来。新手常画成"执行完功能就结束了",漏掉回环。程序不是跑一次就完,是让用户反复操作的;"退出"是用户主动选择才发生,所以要 break 跳出,而不是自然结束。

画图不用画得好看,自己能看懂就行,画在纸上、拍个照都行,明天写代码时对着它写。

流程图里还藏着一个细节:"输入无效"也要有出口。用户可能输个 8、输个 abc,程序不能卡死,得回到"显示菜单"重新来。别小看这条分支,菜单程序一半的友好程度都写在它上面。

通讯录还是记账本,怎么选

两个项目难度、开发流程、代码结构完全一样,只有"字段"和"搜索规则"有点差别:

对比项 通讯录 记账本
一条数据 联系人:姓名 + 电话 + 备注 账目:收入/支出 + 金额 + 用途
数据结构 {"name": ..., "phone": ...} {"type": ..., "amount": ..., "note": ...}
搜索 按姓名或电话模糊搜索 按用途搜索
加分项 修改、电话校验 统计总收入支出
生活场景 手机通讯录 支付宝账单

选哪个都行,关键是两条。一,想稳一点选通讯录,字段简单、好讲清;想演示时效果直观选记账本,有金额统计。二,选定了就坚持做完,不要做到一半换——中途换项目等于推倒重来。确定之后把选择登记给老师,后面几天就按自己选的字段写。

另外提前提个醒:记账本的"金额"要用数字类型(int/float),因为要加减统计;通讯录的"电话"虽然长得像数字,但要当字符串存——电话可能以 0 开头、可能带 -,当数字存会丢信息。

还有一个实际的考虑:演示时长。通讯录字段少,添加一个联系人敲两下就完;记账本要敲三样。如果周五演示时觉得时间紧,就在数据里多预存几条,别现场一条条敲。

把需求翻译成函数清单

需求写的是人话("能添加联系人"),代码要写的是 Python,中间的桥梁就是"我打算用哪个函数实现它"。翻译方法一句话:一条需求 = 一个函数

以通讯录前 4 条需求为例,完整走一遍翻译:

需求(人话) 翻译成函数 函数要干什么(伪代码)
添加联系人 add_contact(contacts) 输入姓名、电话 → 组装成字典 → 放进列表 → 提示成功
查看全部 show_contacts(contacts) 列表空就提示 → 否则带编号打印每条
搜索联系人 search_contact(contacts) 输入关键字 → 遍历判断 in → 打印命中的 → 没找到给提示
删除联系人 delete_contact(contacts) 显示编号 → 输入编号 → 换算下标 → pop → 提示

伪代码(Pseudocode)= 用"半人话半代码"描述思路,不要求能运行,只求把思路说清楚。比如添加功能的伪代码:

伪代码:add_contact
1. 让用户输入姓名 → 存到 name
2. 让用户输入电话 → 存到 phone
3. 造一个字典 {"name": name, "phone": phone}
4. 把这个字典加到 contacts 列表末尾
5. 打印"添加成功"

写伪代码用中文就行,别过早纠结 Python 语法——思路清晰了,语法只是"翻译"问题。也别把一条需求拆成两个函数、或两条需求塞进一个函数:一个功能一个函数,一一对应最好查、最好讲。

这份函数清单要抄在笔记本首页,它有两用:写代码卡壳时,看伪代码就知道下一步干什么;周五答辩讲"怎么做的"时,它就是你的提纲。周二到周五每写完一个函数就在清单上打个勾,本周进度一目了然。它不是今天一日的作业,是这一周的地图——每天开工前扫一眼,你就知道今天该干哪一格。

随堂练习

今天全是纸上作业,不碰电脑写代码,但每一项都认真做,明天开工全靠它们。

  1. 练习一:五周知识小考(10 分钟)——合上教材,在纸上默写:前 5 周每一周学了什么模块、其中 2 个关键知识点、本项目里用在哪。默写完对照上面的知识表检查,漏掉的用红笔补上。这一步是给自己摸底,漏得多说明前面要回头复习。

  2. 练习二:画菜单流程图(15 分钟)——在纸上画出通讯录程序的完整流程图,必须包含:打开程序 → 显示菜单 → 输入选择 → 按数字分支执行 → 回到菜单 → 选退出结束。画完给同桌看,互相找茬:谁漏了"回到菜单"的回环?谁没画"输入无效"的分支?

  3. 练习三:设计数据结构(20 分钟)——不管你做通讯录还是记账本,在纸上写出:① 一条数据的字典长什么样(写 3 个键);② 3 条示例数据;③ 用一句话告诉同桌"为什么用列表套字典"。写完对照上面的示例检查键名是否统一。

  4. 进阶题(可选,做对很加分)——把功能清单第 5 条"修改联系人"翻译成三个问题:用户要输入什么?程序要输出什么?要不要保存?把答案写在纸上。明天和答辩都会用到这个思考方式。

四个练习都做完的同学,可以把今天的收获说给同桌听一遍:项目为什么是"旧知识的新组合"、数据结构为什么选列表套字典。能说顺,说明今天真消化了。

让 AI 帮你把设计把把关

动手写代码前,可以先把数据结构设计发给 AI 验一遍,比自己闷头想更稳。这段提示词直接复制就能用:

场景:让 AI 帮你检验需求分析和数据结构设计
提示词:我是 Python 零基础学员,第 6 周要做通讯录项目。
我的数据结构设计是:所有联系人用一个列表,每个联系人是一个字典,
字段是 name 和 phone。
1. 请评价这个设计有什么优点和缺点;
2. 如果要实现"按编号删除",这个设计够不够用;
3. 请用大白话告诉我,如果我想加"备注"字段,哪些代码要跟着改。
请分点回答,不要一次给完整代码。

报错速查

今天虽然不写代码,但设计阶段常碰到的报错先认识一下,明天写代码时心里有底:

报错信息 什么意思 怎么办
KeyError: 'name' 字典里没有 name 这个键 检查键名拼写:是不是写成 "Name" 或 "姓名" 了,键名必须全项目统一
IndexError: list index out of range 下标越界,取不存在的元素 检查列表长度,contacts[5] 但列表只有 3 个元素就会这样
TypeError: list indices must be integers 用错了下标类型 列表下标必须是数字,contacts["name"] 是错的,应该 contacts[0]["name"]
菜单编号和功能对不上 设计阶段没理顺 回到流程图,把每个编号对应的功能重新列一遍

收个尾

今天干的全是"想清楚"的活:五周知识盘过一遍,需求翻译成了函数清单,数据结构定成了"列表套字典",菜单流程图画完了。你脑子里现在应该有一张完整的施工图——这就是专业程序员开工前的第一关。

明天正式动工,第一天的目标是搭出"最小可跑版":菜单循环 + 添加 + 查看 + 退出,数据先只放内存、不碰文件。明天你会第一次体会到"程序在手里跑起来"的成就感,记得带上今天画的流程图。今天的活看着不起眼,但"先想清楚再动手"这个习惯,比任何一行代码都值钱,往后每周的项目都要靠它。