文章

Python 首批细教程 · 02A:用函数和模块做一个成绩统计 CLI

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

对应原仓库Day01-15/06.函数和模块的使用.mdDay01-15/07.字符串和常用数据结构.mdDay01-15/11.文件和异常.md

已提供可运行示例/tutorial-assets/python-100-days/02a-score-cli/(站点源码路径:blog-src/static/tutorial-assets/python-100-days/02a-score-cli/

这一篇不讲“函数有什么好处”,直接做一个能用的小工具:从终端录入学生成绩,输出平均分、最高分、及格人数和等级分布。

最终效果

请输入:姓名,分数;输入 q 结束
> 张三,88
> 李四,92
> 王五,77
> 赵六,59
> q

总人数: 4
平均分: 79.00
最高分: 李四 92
及格人数: 3
等级分布: {'A': 1, 'B': 1, 'C': 1, 'D': 1}

Step 1:把输入解析拆成函数

直接使用示例目录里的 score_utils.py(站点源码路径:blog-src/static/tutorial-assets/python-100-days/02a-score-cli/score_utils.py):

def parse_record(text: str) -> tuple[str, int]:
    name, score_text = text.split(",")
    score = int(score_text.strip())
    if not 0 <= score <= 100:
        raise ValueError("分数必须在 0 到 100 之间")
    return name.strip(), score


def get_level(score: int) -> str:
    if score >= 90:
        return "A"
    if score >= 80:
        return "B"
    if score >= 60:
        return "C"
    return "D"

这里对应的就是原仓库里“用函数封装重复逻辑”的思想。parse_recordget_level 都是可复用模块,而不是散在主程序里的一堆判断。

Step 2:写统计函数

继续在 score_utils.py 里补:

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


def level_counter(scores: list[int]) -> dict[str, int]:
    counter = {"A": 0, "B": 0, "C": 0, "D": 0}
    for score in scores:
        counter[get_level(score)] += 1
    return counter

这一步就是把列表操作、循环和字典结合起来。

Step 3:写主程序

直接使用示例目录里的 main.py(站点源码路径:blog-src/static/tutorial-assets/python-100-days/02a-score-cli/main.py):

from score_utils import average, level_counter, parse_record


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

    print("请输入:姓名,分数;输入 q 结束")
    while True:
        text = input("> ").strip()
        if text.lower() == "q":
            break
        try:
            records.append(parse_record(text))
        except ValueError as err:
            print(f"输入无效:{err}")

    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"及格人数: {sum(score >= 60 for score in scores)}")
    print(f"等级分布: {level_counter(scores)}")


if __name__ == "__main__":
    main()

运行:

cd blog-src/static/tutorial-assets/python-100-days/02a-score-cli
python main.py

这一篇到底学什么

不是“学会了几个语法点”,而是练下面这几个能力:

  1. 输入解析:把字符串变成结构化数据。
  2. 函数拆分:每个函数只做一件事。
  3. 模块复用:统计逻辑和交互逻辑分离。
  4. 异常处理:错误输入不让程序崩掉。

进阶任务

  1. 把数据保存到 scores.txt
  2. 允许用户从文件读取成绩。
  3. level_counter 改成使用 collections.Counter

常见坑

  • split(",") 后不做 strip(),会带空格。
  • 分数不校验范围,188 也被算进去。
  • 所有逻辑都塞进 main(),后面没法测试。