找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4076

积分

0

好友

558

主题
发表于 12 小时前 | 查看: 7| 回复: 0

那天我刚想下班摸鱼,办公室门一开,班主任冲进来就问:“东哥,你会不会搞那个……Python?帮我弄个成绩分析,我这Excel都要被我点炸了。” 我看了一眼她那张一万多行的表,脑袋“嗡”了一下:得,经典背锅现场这不就来了嘛。

一边给她倒水,我一边琢磨:要不就整一个简单的桌面程序,点几下按钮就能算平均分、查挂科名单、看年级前十那种。对老师来说,打开个浏览器都觉得复杂,还是老老实实用 Tkinter 弹个窗口,数据用 SQLite3 丢在本地一个文件里,拷U盘就能带走,简单方便。

说干就干。最基础的就是建库,我随手写了个初始化的函数,虽然看着糙,但管用:

import sqlite3

DB_PATH = "score.db"

def init_db():
    conn = sqlite3.connect(DB_PATH)
    cur = conn.cursor()
    cur.execute("""
        CREATE TABLE IF NOT EXISTS students (
            id      INTEGER PRIMARY KEY AUTOINCREMENT,
            name    TEXT NOT NULL,
            math    REAL NOT NULL,
            chinese REAL NOT NULL,
            english REAL NOT NULL
        )
    """)
    conn.commit()
    conn.close()

这玩意儿的好处是啥?就算老师手一哆嗦把 score.db 给删了,下次再打开程序,它自己又能给你建一张新表。顶多就是数据没了,但程序照常跑,属于那种“人没了系统还在”的顽强。

接下来就是最日常的需求:录入一个学生成绩。老师的要求特别直白:“我就想输名字、输分数,点一下按钮,完事。” 其他什么CRUD、API这些词,就别跟她讲了。行,那就按她的意思来:

def add_student(name, math, chinese, english):
    conn = sqlite3.connect(DB_PATH)
    cur = conn.cursor()
    cur.execute(
        "INSERT INTO students(name, math, chinese, english) VALUES (?, ?, ?, ?)",
        (name, math, chinese, english)
    )
    conn.commit()
    conn.close()

别看就这么几行,后来还真救了我一次。有天老师很激动地跟我说:“我刚才不小心点了两次添加怎么办?” 我心里咯噔一下,寻思是不是得加个撤销功能。冷静下来翻了翻数据库,好家伙,她第二次输的时候把数学分从95改成了96,这不就是“人工纠错”嘛。我赶紧顺势说:“这说明咱们系统有智能纠偏能力。”——这叫算法辅助教学,懂吧?

光能存还不够,老师最关心的是谁考砸了,谁需要叫家长。这个功能写起来就有点“阴间”了,一边写我一边庆幸自己毕业多年。先得有个基础统计,算算平均分、最高分这些:

def calc_stats():
    conn = sqlite3.connect(DB_PATH)
    cur = conn.cursor()
    cur.execute("""
        SELECT 
            COUNT(*) as total,
            AVG(math), AVG(chinese), AVG(english),
            MAX(math), MAX(chinese), MAX(english)
        FROM students
    """)
    row = cur.fetchone()
    conn.close()
    return {
        "total": row[0],
        "avg_math": row[1],
        "avg_chinese": row[2],
        "avg_english": row[3],
        "max_math": row[4],
        "max_chinese": row[5],
        "max_english": row[6],
    }

写完我自己先跑了一遍,看到 AVG 函数算出来小数点后那一大串数字,脑子里立刻浮现出老师拿着计算器对着屏幕一位位核对的样子。得,后面做UI的时候,我干脆都把数字四舍五入到一位小数,不给她留下任何“质疑程序精度”的机会。

说了半天数据库,得回到Tkinter这边了。老师的指示非常明确:“要能点,能看,别让我记命令。” 没辙,给她糊一个简单粗暴的窗口吧。当时大概是这么搭的框架:

import tkinter as tk
from tkinter import messagebox

def build_ui():
    root = tk.Tk()
    root.title("学生成绩分析系统")

    tk.Label(root, text="姓名").grid(row=0, column=0)
    tk.Label(root, text="数学").grid(row=1, column=0)
    tk.Label(root, text="语文").grid(row=2, column=0)
    tk.Label(root, text="英语").grid(row=3, column=0)

    name_var = tk.StringVar()
    math_var = tk.StringVar()
    chi_var = tk.StringVar()
    eng_var = tk.StringVar()

    tk.Entry(root, textvariable=name_var).grid(row=0, column=1)
    tk.Entry(root, textvariable=math_var).grid(row=1, column=1)
    tk.Entry(root, textvariable=chi_var).grid(row=2, column=1)
    tk.Entry(root, textvariable=eng_var).grid(row=3, column=1)

    result_box = tk.Text(root, width=40, height=10)
    result_box.grid(row=0, column=2, rowspan=6, padx=10)

    def on_add():
        name = name_var.get().strip()
        try:
            math = float(math_var.get())
            chi = float(chi_var.get())
            eng = float(eng_var.get())
        except ValueError:
            messagebox.showerror("错误", "分数必须是数字,别夹中文逗号了…")
            return

        if not name:
            messagebox.showwarning("提示", "姓名不能为空")
            return

        add_student(name, math, chi, eng)
        messagebox.showinfo("成功", "已保存")
        name_var.set("")
        math_var.set("")
        chi_var.set("")
        eng_var.set("")

    def on_stats():
        data = calc_stats()
        result_box.delete("1.0", tk.END)
        if data["total"] == 0:
            result_box.insert(tk.END, "还没有任何学生数据\n")
            return
        result_box.insert(tk.END, f"总人数:{data['total']}\n")
        result_box.insert(tk.END, f"数学 平均:{data['avg_math']:.1f}  最高:{data['max_math']}\n")
        result_box.insert(tk.END, f"语文 平均:{data['avg_chinese']:.1f}  最高:{data['max_chinese']}\n")
        result_box.insert(tk.END, f"英语 平均:{data['avg_english']:.1f}  最高:{data['max_english']}\n")

    tk.Button(root, text="添加成绩", command=on_add).grid(row=4, column=1, sticky="ew", pady=5)
    tk.Button(root, text="统计分析", command=on_stats).grid(row=5, column=1, sticky="ew", pady=5)

    return root

中间那个 result_box 文本框特别重要。一开始我偷懒,所有结果都用 messagebox 弹窗显示,老师用了一会儿就跟我说:“你这玩意儿弹得我想砸电脑。” 我赶紧改成右边放一个大文本框,所有统计信息都往里面刷新,视觉上瞬间就“温柔”多了。

你以为这就结束了?并没有。真正的大坑在“挂科名单”这里。老师轻描淡写地补了一句:“最好能看看谁挂了两门以上。” 好嘛,一听就知道得写带条件的SQL。我一边心里碎碎念,一边加了个函数,写法比较直接:

def get_failed_students(threshold=60):
    conn = sqlite3.connect(DB_PATH)
    cur = conn.cursor()
    cur.execute("""
        SELECT name, math, chinese, english
        FROM students
    """)
    res = []
    for name, m, c, e in cur.fetchall():
        fail_count = sum(score < threshold for score in (m, c, e))
        if fail_count >= 2:
            res.append((name, m, c, e, fail_count))
    conn.close()
    return res

然后在UI里,我偷偷加了个对应的按钮和事件:

    def on_failed():
        rows = get_failed_students()
        result_box.delete("1.0", tk.END)
        if not rows:
            result_box.insert(tk.END, "没有两门以上不及格的学生,老师今天可以开心回家了。\n")
            return
        for name, m, c, e, cnt in rows:
            line = f"{name}  数学:{m}  语文:{c}  英语:{e}  挂科数:{cnt}\n"
            result_box.insert(tk.END, line)

    tk.Button(root, text="挂科名单", command=on_failed).grid(row=6, column=1, sticky="ew", pady=5)

那天我把新版本拷到老师电脑上,她点开“挂科名单”按钮,盯着屏幕沉默了大概三秒钟,然后回头跟我说:“这个按钮,你别让学生看到。” 我秒懂:得,这属于内部运维工具,不对普通用户开放。

最后,得把这些零散的模块串起来,不然总有人复制了代码少一块,回头又来问“为什么点按钮没反应”。主函数就很简单:

if __name__ == "__main__":
    init_db()
    app = build_ui()
    app.mainloop()

整套系统没啥高大上的,就是一个基于 Tkinter 和 SQLite3 的本地小工具,但胜在足够接地气:老师双击一个图标,就能录入成绩、看平均分、查挂科名单;数据库就一个 score.db 文件,U盘拷来拷去也不怕环境问题;哪天要是真想弄到服务器上,把 SQLite3 换成 MySQL 或别的,也无非是改掉那几个 sqlite3.connect 的地方,核心逻辑基本不用动。

做完这个东西之后,老师每次见我都笑眯眯的。唯一的小“后遗症”就是,她现在看到我就说:“东哥,下次再给我加个导出Excel的功能哈。” 行吧,下次的事下次再说,说不定下次的需求就变成“学生成绩可视化大屏系统”了……

这个小项目虽然简单,但很好地展示了如何用 Python 快速解决身边的具体问题。如果你也对这类实用的桌面开发或数据处理感兴趣,欢迎来 云栈社区 一起交流探讨,这里有很多类似的实战项目和经验分享。




上一篇:从生活吐槽到代码调试:详解“最近时刻”算法Python实现与常见坑点
下一篇:魔兽世界任务系统与暴雪团队管理:Jeff Kaplan深度复盘游戏设计成败
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-16 21:39 , Processed in 0.484945 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表