文章

Python 教程拆解索引 · 02:基础语法与语言地基

#248 · 2026-05-13 · Python 教程拆解

说明:本文是基于 Day01-15/Day16-20/ 的原创教学整理,不复写原教程内容。

系列导航01 学习地图|02 语言地基|03 工程配套

本篇对应材料Day01-15/Day16-20/,重点关联 06.函数和模块的使用.md07.字符串和常用数据结构.md11.文件和异常.md

定位更正:这一页现在只作为“基础语法专题入口”,不再把 Day01-20 压成一篇教程。真正的教学正文改成下面这些细教程。

本章细教程

已经拆开的源文件

原仓库文件 主题 教程
Day01-15/06.函数和模块的使用.md 函数拆分、模块化、CLI 输入 02A
Day01-15/11.文件和异常.md JSON 持久化、文件读写、异常处理 02B

下一批应该继续拆的文件

  • Day01-15/02.语言元素.md
  • Day01-15/03.分支结构.md
  • Day01-15/04.循环结构.md
  • Day01-15/07.字符串和常用数据结构.md
  • Day16-20/16-20.Python语言进阶.md

这一段最容易学成“我看懂了变量、函数、列表、字典,但我还是不会写程序”。

原因很简单:只看知识点,不把它们拼起来。

之前我把这段直接压成一篇“成绩分析器”,你指出的问题是对的:这会让目录层级和教学颗粒度都错位。 所以现在把它收回成索引页,正文拆到具体小教程里。

今天你要做出的结果

我们会写出下面这样一个命令行程序:

请输入学生姓名和分数,格式如 张三,88,输入 q 结束
> 张三,88
> 李四,92
> 王五,77
> q

共 3 人
平均分: 85.67
最高分: 李四 92
及格人数: 3

Step 1:先把“函数”真正用起来

新建 practice/day02/score_utils.py

def parse_record(line: str) -> tuple[str, int]:
    name, score_text = line.split(",")
    return name.strip(), int(score_text.strip())


def average(scores: list[int]) -> float:
    return sum(scores) / len(scores) if scores else 0.0


def count_pass(scores: list[int], pass_line: int = 60) -> int:
    return sum(1 for score in scores if score >= pass_line)

这里你就已经在练三件事:

  1. 输入处理;
  2. 函数拆分;
  3. 列表上的聚合操作。

Step 2:写主程序,把模块接起来

新建 practice/day02/score_app.py

from score_utils import parse_record, average, count_pass


def main():
    records: list[tuple[str, int]] = []

    print("请输入学生姓名和分数,格式如 张三,88,输入 q 结束")
    while True:
        text = input("> ").strip()
        if text.lower() == "q":
            break
        try:
            records.append(parse_record(text))
        except ValueError:
            print("输入格式错误,请重新输入,例如:张三,88")

    if not records:
        print("没有录入任何数据")
        return

    scores = [score for _, score in records]
    top_name, top_score = max(records, key=lambda item: item[1])

    print()
    print(f"共 {len(records)} 人")
    print(f"平均分: {average(scores):.2f}")
    print(f"最高分: {top_name} {top_score}")
    print(f"及格人数: {count_pass(scores)}")


if __name__ == "__main__":
    main()

运行:

cd practice/day02
python score_app.py

Step 3:把“文件和异常”也接上

前面你是手输数据,现在再做一个文件版本。

新建 practice/day02/scores.txt

张三,88
李四,92
王五,77
赵六,59

新建 practice/day02/score_file_app.py

from score_utils import parse_record, average, count_pass


def main():
    records = []
    try:
        with open("scores.txt", "r", encoding="utf-8") as file:
            for line in file:
                line = line.strip()
                if line:
                    records.append(parse_record(line))
    except FileNotFoundError:
        print("没有找到 scores.txt")
        return

    scores = [score for _, score in records]
    top_name, top_score = max(records, key=lambda item: item[1])

    print(f"平均分: {average(scores):.2f}")
    print(f"最高分: {top_name} {top_score}")
    print(f"及格人数: {count_pass(scores)}")


if __name__ == "__main__":
    main()

运行:

python score_file_app.py

你在这个小练习里到底学到了什么

这就是 Day01-20 最应该教会你的东西:

  • 函数:把逻辑拆出去,而不是写一坨。
  • 模块:让主程序更短、更清晰。
  • 列表 / 元组:组织数据。
  • 异常处理:让程序别一出错就炸掉。
  • 输入输出:让代码碰到真实世界。

这比背“什么是函数”“什么是模块”有用得多。

进阶一小步:把它改成生成器思维

如果你继续往 Day16-20 走,可以试着把读取文件改成生成器:

def read_records(path: str):
    with open(path, "r", encoding="utf-8") as file:
        for line in file:
            line = line.strip()
            if line:
                yield parse_record(line)

然后主程序里改成:

records = list(read_records("scores.txt"))

这就是从“会写函数”走向“开始理解迭代和延迟计算”的过渡。

本篇练习

  1. 给程序加一个“不及格名单”输出。
  2. 把分数等级改成 A / B / C / D。
  3. 允许用户从文件模式和手输模式二选一。

常见坑

  • 坑 1:所有逻辑都写在 main() 里。 这会让后面完全没法复用。
  • 坑 2:没做输入校验。 一条坏数据就会让程序崩掉。
  • 坑 3:模块导入报错。 记得在同目录下运行,或者回到项目根目录后用包结构组织。

上一篇Python 教程拆解 · 01:按源文件拆,而不是把很多天并成一篇
下一篇Python 教程拆解 · 03:前端、环境与数据库