20252328 2025-2026-2 《Python程序设计》实验四报告
20252328 2025-2026-2 《Python程序设计》实验四报告
课程:《Python程序设计》
班级: 2523
姓名: 向一
学号:20252328
实验教师:王志强
实验日期:2026年5月16日
必修/选修: 公选课
1.实验内容
Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
这次实验利用阿里云QODER CN,开发了一款基于 Python PyQt6 的桌面应用程序——SmartDaily(智能每日助手),为用户提供简单的日常生活管理服务,包含天气,日记,记账,日程安排,每日总结。
!!!完整代码仓库
具体实验内容包括:
1.1 功能模块开发
(1)天气查询模块
集成和风天气和高德地图双 API,实现实时天气数据获取
支持城市搜索和切换功能
显示温度、湿度、风力、空气质量等详细信息
提供未来几小时的天气趋势预测
实现本地缓存机制,减少 API 调用频率
(2)日程管理模块
实现今日日程的添加、查看、删除功能
支持设置日程的开始时间和结束时间
提供双击或右键菜单标记日程完成状态
基于 APScheduler 实现定时提醒功能
通过系统托盘弹出通知提醒用户
自动清理 7 天前的已完成日程
(3)快速记账模块
提供简洁的支出录入界面(金额、类别、备注)
实时计算并显示今日总支出
实现历史记账明细查看功能
支持按日期和类别筛选记录
提供删除记账记录功能
(4)日记记录模块
实现日记编写功能(支持标题和正文)
提供历史记录列表,按日期倒序排列
支持查看、编辑和删除已有日记
在日终总结时展示当日日记内容
(5)AI 智能建议模块
集成 DeepSeek 大语言模型 API
根据天气、日程、支出等信息生成个性化建议
实现本地规则模板降级方案(API 不可用时)
提供晨间建议和日终 AI 点评功能
(6)系统功能
实现开始/结束今日流程管理
提供统一设置中心(AI 配置、城市设置)
实现系统托盘最小化功能
1.2 技术实现要点
GUI 框架: 使用 PyQt6 构建图形用户界面
数据库: 使用 SQLite3 实现数据持久化存储
网络请求: 使用 httpx 库进行 HTTP API 调用
定时任务: 使用 APScheduler 实现后台任务调度
异步编程: 使用 QThread 避免阻塞主 UI 线程
事件驱动: 基于 PyQt6 信号槽机制实现模块解耦
设计模式: 应用单例模式、策略模式、上下文管理器等
2. 实验过程及结果
2.1 实验环境搭建
开发环境配置:
操作系统: Windows 11
Python 版本: 3.14
IDE: VS Code / PyCharm
依赖库安装:
bash
pip install PyQt6 APScheduler httpx
项目结构创建:
DailyAssistant/├── main.py # 程序入口
├── config/ # 配置模块
│ ├── paths.py # 路径工具
│ └── theme.json # 主题配置
├── core/ # 核心模块
│ ├── db_manager.py # 数据库管理器
│ ├── event_bus.py # 事件总线
│ └── scheduler.py # 任务调度器
├── services/ # 服务模块
│ ├── weather.py # 天气服务
│ └── advice_engine.py # AI 建议引擎
├── ui/ # 界面模块
│ ├── main_window.py # 主窗口
│ ├── weather_card.py # 天气卡片
│ ├── schedule_widget.py # 日程组件
│ ├── expense_widget.py # 记账组件
│ ├── note_widget.py # 日记组件
│ └── dialogs.py # 对话框集合
└── assets/ # 资源文件
└── icon.png # 应用图标
2.2 数据库设计与实现
步骤1: 创建 DatabaseManager 单例类
class DatabaseManager:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
@contextmanager
def get_connection(self):
conn = sqlite3.connect(self.db_path)
conn.row_factory = sqlite3.Row
try:
yield conn
conn.commit()
except Exception as e:
conn.rollback()
raise e
finally:
conn.close()
步骤2: 初始化数据表结构
创建 5 张核心数据表:weather_log(天气日志)、schedules(日程)、notes(笔记)、expenses(支出)、user_settings(用户设置)。
步骤3: 实现 CRUD 接口
为每张表提供增删改查方法,所有 SQL 语句使用参数化查询防止注入:
def add_schedule(self, title, start_time=None, end_time=None, reminder_time=None, date=None):
if not date:
date = datetime.now().strftime("%Y-%m-%d")
created_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with self.get_connection() as conn:
cursor = conn.execute(
'''INSERT INTO schedules (title, date, start_time, end_time, reminder_time, is_completed, created_at)
VALUES (?, ?, ?, ?, ?, 0, ?)''',
(title, date, start_time, end_time, reminder_time, created_at)
)
return cursor.lastrowid
2.3 事件总线实现
步骤1: 创建 EventBus 单例
基于 PyQt6 的 QObject 和 pyqtSignal 实现全局事件总线:
class EventBus(QObject):
_instance = None
weather_updated = pyqtSignal(dict)
schedule_changed = pyqtSignal()
expense_added = pyqtSignal(dict)
expense_deleted = pyqtSignal(dict)
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
步骤2: 模块间通信
发送方发射信号,接收方连接槽函数,实现解耦:
# 发送信号(ExpenseWidget)
event_bus.expense_added.emit({"amount": 50, "category": "餐饮"})
# 接收信号(MainWindow 或其他组件)
event_bus.expense_added.connect(self.on_expense_changed)
结果: 模块间耦合度降低,代码可维护性提高。
2.4 定时调度器实现
步骤1: 创建 SchedulerWorker 线程
继承 QThread,在后台运行 APScheduler:
class SchedulerWorker(QThread):
reminder_triggered = pyqtSignal(dict)
def run(self):
self.scheduler = BackgroundScheduler(timezone='Asia/Shanghai')
# 每分钟检查提醒
self.scheduler.add_job(
func=self._check_reminders,
trigger='interval',
minutes=1,
id='check_reminders'
)
# 每天凌晨清理数据
self.scheduler.add_job(
func=self._cleanup_old_data,
trigger='cron',
hour=0, minute=0,
id='cleanup_data'
)
self.scheduler.start()
while self._is_running:
self.msleep(1000)
步骤2: 实现提醒检查逻辑
遍历今日未完成日程,判断提醒时间是否到期:
def _check_reminders(self):
now = datetime.now()
schedules = db_manager.get_today_schedules()
for schedule in schedules:
if schedule.get('is_completed', 0):
continue
reminder_time = schedule.get('reminder_time')
if not reminder_time:
continue
reminder_dt = datetime.strptime(reminder_time[:16], "%Y-%m-%d %H:%M")
if reminder_dt <= now and (now - reminder_dt).total_seconds() < 60:
self.reminder_triggered.emit({
'title': schedule['title'],
'start_time': schedule.get('start_time', '')
})
结果: 定时提醒准确触发,系统托盘通知正常显示,不阻塞 UI。
2.5 天气服务实现
步骤1: 创建 WeatherService 类
实现多源 API 集成和降级策略:
class WeatherService:
def __init__(self):
self.qweather_key = db_manager.get_setting("qweather_api_key", "")
self.amap_key = db_manager.get_setting("amap_api_key", "")
def fetch_weather(self, city_name=None):
if city_name is None:
city_name = db_manager.get_setting("city_name", "北京")
# 优先尝试和风天气
if self.qweather_key:
data = self._fetch_qweather(city_name)
if data:
return data
# 降级到高德地图
data = self._fetch_amap(city_name)
if data:
return data
# 最后尝试缓存
return self._get_cached_data(city_name)
步骤2: 实现和风天气 API 调用
并行获取实况、预报、空气质量等多维度数据:
def _fetch_qweather(self, city_name):
location_id = self._get_location_id(city_name, source="qweather")
with httpx.Client(timeout=8) as client:
headers = {"Authorization": f"{self.qweather_key}"}
now_r = client.get("https://devapi.qweather.com/v7/weather/now",
params={"location": location_id}, headers=headers)
daily_r = client.get("https://devapi.qweather.com/v7/weather/3d",
params={"location": location_id}, headers=headers)
air_r = client.get("https://devapi.qweather.com/v7/air/now",
params={"location": location_id}, headers=headers)
now = now_r.json()["now"]
daily = daily_r.json()["daily"][0]
air = air_r.json()["now"]
return {
"temperature": float(now["temp"]),
"humidity": int(now["humidity"]),
"condition_text": now["text"],
"aqi": int(air["aqi"]),
"temp_max": float(daily["tempMax"]),
"temp_min": float(daily["tempMin"]),
# ... 更多字段
}
步骤3: 实现城市地理位置查询
调用地理编码 API 将城市名称转换为 Location ID:
def _get_location_id(self, city_name, source="qweather"):
with httpx.Client(timeout=8) as client:
if source == "qweather":
resp = client.get("https://geoapi.qweather.com/v2/city/lookup",
params={"location": city_name, "number": 1},
headers={"Authorization": f"{self.qweather_key}"})
data = resp.json()
if data.get("code") == "200" and data.get("location"):
return data["location"][0]["id"]
结果: 天气数据获取成功,API 降级机制有效,缓存减少重复调用。
2.6 AI 建议引擎实现
步骤1: 创建 AdviceEngine 类
支持在线 AI 和本地规则两种策略:
class AdviceEngine:
def generate(self, weather_data, schedule_status=None, expense_total=0, note_content=""):
config = self.get_config()
# 检查 AI 是否启用
if not config.get("ai_enabled"):
return self._rule_based_advice(weather_data)
# 检查 API Key
if not config.get("api_key"):
return "⚠️ AI 建议未启用:请在设置中心填写 DeepSeek API Key。"
try:
return self._call_llm_api(weather_data, schedule_status, expense_total, note_content, config)
except Exception as e:
# 降级到本地规则
return self._rule_based_advice(weather_data)
步骤2: 实现 DeepSeek API 调用
构造提示词,调用大模型生成个性化建议:
def _call_llm_api(self, weather, schedules, expenses, note, config):
prompt = f"""
你是一位贴心的生活助手。请根据以下信息给出一段简短、温馨的今日建议(120字以内):
【当前天气】
- 实时:{weather.get('condition_text')},{weather.get('temperature')}°C
- 今日最高/最低:{weather.get('temp_max')}°C / {weather.get('temp_min')}°C
- 空气质量:AQI {weather.get('aqi')}
【今日安排】
- 日程进度:{schedules}
- 已支出:{expenses}元
- 笔记:{note if note else '无'}
请结合当前天气和未来趋势,给出穿衣、出行、健康等方面的实用建议。语气要温暖贴心。
"""
payload = {
"model": config.get("model", "deepseek-chat"),
"messages": [{"role": "user", "content": prompt}],
"temperature": 0.7
}
with httpx.Client(timeout=8) as client:
response = client.post(
config["api_url"],
json=payload,
headers={"Authorization": f"Bearer {config['api_key']}"}
)
return response.json()["choices"][0]["message"]["content"].strip()
步骤3: 实现本地规则降级
基于温度和天气代码返回预设模板:
def _rule_based_advice(self, weather):
temp = weather.get("temperature", 20)
code = weather.get("condition_code", 0)
if temp > 28:
return "🌞 今日气温较高,注意防晒补水。"
if code in [61, 63, 65, 80]:
return "🌧 降水概率大,请携带雨具。"
if temp < 10:
return "❄️ 气温较低,请注意保暖。"
return "🌤 今日天气平稳,适宜日常通勤。"
结果: AI 建议生成成功,内容丰富且个性化;API 失败时自动降级,保证功能可用性。
2.7 主窗口与界面整合
步骤1: 创建 MainWindow 类
整合所有功能模块,设置整体布局:
class MainWindow(QMainWindow):
def _setup_ui(self):
central_widget = QWidget()
main_layout = QVBoxLayout()
# 顶部工具栏
toolbar_layout = QHBoxLayout()
settings_btn = QPushButton("⚙️ 设置")
settings_btn.clicked.connect(self.show_settings)
toolbar_layout.addWidget(settings_btn)
main_layout.addLayout(toolbar_layout)
# 天气卡片
self.weather_card = WeatherCard()
main_layout.addWidget(self.weather_card)
# 日程管理
self.schedule_widget = ScheduleWidget()
main_layout.addWidget(self.schedule_widget)
# 记账和笔记(横向布局)
record_layout = QHBoxLayout()
self.note_widget = NoteWidget()
self.expense_widget = ExpenseWidget()
record_layout.addWidget(self.note_widget)
record_layout.addWidget(self.expense_widget)
main_layout.addLayout(record_layout)
# 开始/结束今日按钮
self.day_action_btn = QPushButton("🌅 开始今日")
self.day_action_btn.clicked.connect(self.handle_day_action)
main_layout.addWidget(self.day_action_btn)
self.setCentralWidget(central_widget)
步骤2: 实现系统托盘
def _setup_tray(self):
self.tray_icon = QSystemTrayIcon(self)
self.tray_icon.setIcon(QIcon("assets/icon.png"))
self.tray_icon.setToolTip("Smart Daily Assistant")
tray_menu = QMenu()
show_action = QAction("显示主窗口", self)
show_action.triggered.connect(self.show)
tray_menu.addAction(show_action)
quit_action = QAction("退出", self)
quit_action.triggered.connect(QApplication.quit)
tray_menu.addAction(quit_action)
self.tray_icon.setContextMenu(tray_menu)
self.tray_icon.show()
def closeEvent(self, event):
if self.tray_icon.isVisible():
self.hide()
self.tray_icon.showMessage("Smart Daily", "助手已最小化到托盘")
event.ignore()
else:
event.accept()
步骤3: 实现日程变化监听
连接 EventBus 信号,自动刷新日程列表:
def _connect_signals(self):
event_bus.schedule_changed.connect(self.on_schedule_changed)
task_scheduler.worker.reminder_triggered.connect(self.show_reminder_notification)
def on_schedule_changed(self):
if hasattr(self, 'schedule_widget'):
self.schedule_widget.load_schedules()
def show_reminder_notification(self, reminder_data):
title = reminder_data.get('title', '日程提醒')
message = f"📅 {title}"
self.tray_icon.showMessage("日程提醒", message, QSystemTrayIcon.MessageIcon.Information, 5000)
QMessageBox.information(self, "日程提醒", message)
结果: 使主窗口布局合理,各模块协调工作,系统托盘功能正常。
2.8 各功能组件实现
- (1)WeatherCard 天气卡片
异步加载天气数据(使用 QThread)
显示温度、湿度、风力、空气质量
提供城市搜索和切换功能
调用 AdviceEngine 生成智能建议
关键代码:
def load_weather(self):
self.refresh_btn.setEnabled(False)
self.refresh_btn.setText("加载中...")
self.weather_fetcher = WeatherFetcher(self.current_city)
self.weather_fetcher.finished.connect(self.on_weather_loaded)
self.weather_fetcher.error.connect(self.on_weather_error)
self.weather_fetcher.start()
def on_weather_loaded(self, data):
self.refresh_btn.setEnabled(True)
self.refresh_btn.setText("🔄 刷新")
temp = data.get('temperature', '--')
humidity = data.get('humidity', '--')
condition = data.get('condition_text', '未知')
weather_text = f"🌡️ 温度: {temp}°C\n💧 湿度: {humidity}%\n☁️ 天气: {condition}"
self.weather_info_label.setText(weather_text)
event_bus.weather_updated.emit(data)
self.generate_advice(data)
- (2)ScheduleWidget 日程组件
加载并显示今日日程列表
添加日程对话框(标题、开始时间、结束时间)
右键菜单操作(标记完成、删除)
双击切换完成状态
添加日程时同步注册定时提醒任务
关键代码:
def add_schedule(self):
dialog = QDialog(self.window())
title_input = QLineEdit()
start_time_edit = QDateTimeEdit()
end_time_edit = QDateTimeEdit()
def on_save():
title = title_input.text().strip()
if not title:
QMessageBox.warning(dialog, "提示", "请输入日程标题")
return
start_time = start_time_edit.dateTime().toString("yyyy-MM-dd HH:mm:ss")
date = start_time_edit.dateTime().toString("yyyy-MM-DD")
schedule_id = db_manager.add_schedule(
title=title, start_time=start_time,
end_time=end_time_edit.dateTime().toString("yyyy-MM-DD HH:mm:ss"),
reminder_time=start_time, date=date
)
# 添加定时提醒
task_scheduler.add_reminder_job(schedule_id, start_time)
dialog.accept()
self.load_schedules()
save_btn.clicked.connect(on_save)
dialog.exec()
-
(3)ExpenseWidget 记账组件
快速录入支出(金额、类别、备注)
实时显示今日总支出
监听 expense_added/deleted 信号自动更新总额
打开 ExpenseHistoryDialog 查看历史明细
关键代码:def add_expense(self): amount_text = self.amount_input.text().strip() if not amount_text: return try: amount = float(amount_text) except ValueError: return if amount <= 0: return category = self.category_combo.currentText() remark = self.remark_input.text().strip() db_manager.add_expense(amount, category, remark) event_bus.expense_added.emit({"amount": amount, "category": category}) self.amount_input.clear() self.remark_input.clear() self.update_total() -
(4)NoteWidget 日记组件
DiaryManagerDialog 实现完整日记管理
左侧历史列表,右侧编辑区域
支持标题和正文
保存后刷新历史列表
关键代码:def save_current_note(self): title = self.title_input.text() content = self.content_editor.toPlainText() if not content.strip() and not title.strip(): QMessageBox.warning(self, "提示", "标题和正文不能同时为空") return db_manager.save_note(self.current_date, content, title) self.load_history_list() QMessageBox.information(self, "成功", "日记已保存!") -
(5)SettingsDialog 设置中心
使用 QStackedWidget 实现多页面切换
AI 设置(启用开关、API Key、模型名称、URL)
主题设置(浅色/深色)
城市设置
关于页面
关键代码:def save_all_settings(self): ai_enabled = "true" if self.ai_enabled_check.currentIndex() == 0 else "false" db_manager.set_setting("ai_enabled", ai_enabled) db_manager.set_setting("api_key", self.api_key_input.text().strip()) db_manager.set_setting("ai_model", self.model_input.text().strip()) db_manager.set_setting("current_city", self.city_input.text().strip()) QMessageBox.information(self, "成功", "设置已保存!") self.accept() -
(6)DaySummaryDialog 日终总结
汇总今日日程完成情况
统计今日总支出
展示当日日记内容
调用 AI 生成综合点评
关键代码:def load_summary(self): schedules = db_manager.get_today_schedules() completed_count = sum(1 for s in schedules if s.get("is_completed", 0)) expense_total = db_manager.get_today_expense_total() note_obj = db_manager.get_note(self.today) note_content = note_obj.get("content", "") if note_obj else "" # 获取 AI 点评 try: weather_service = WeatherService() weather_data = weather_service.fetch_weather() engine = AdviceEngine() ai_comment = engine.generate( weather_data, {"total": len(schedules), "completed": completed_count}, expense_total, note_content ) except: ai_comment = "💡 今日辛苦了!好好休息,明天继续加油。" summary = f"📅 日期: {self.today}\n\n" summary += f"🤖 AI 每日点评:\n{ai_comment}\n\n" summary += f"📋 日程: {len(schedules)} 项 | 已完成: {completed_count} 项\n" summary += f"💰 今日支出: ¥{expense_total:.2f}\n\n" if note_content: summary += f"📝 今日笔记:\n{note_content}\n\n" self.summary_text.setPlainText(summary)2.9 程序启动流程
main.py 入口文件:
if __name__ == "__main__": app = QApplication(sys.argv) # 应用主题 theme_manager = ThemeManager() theme_manager.apply_theme(app) # 启动定时调度器 task_scheduler.start() # 创建并显示主窗口 window = MainWindow() window.show() exit_code = app.exec() # 停止调度器 task_scheduler.stop() sys.exit(exit_code)2.10 测试结果
-
主界面截图: 展示整体布局和所有功能模块

-
日程管理截图: 展示日程列表和添加对话框

-
提醒通知截图: 系统托盘弹出的日程提醒

-
记账界面截图: 快速录入和历史明细表格

-
日记编辑截图: 日记编写界面和历史列表

-
日终总结截图: AI 点评和数据汇总

视频演示
性能指标:
启动时间: 约 2-3 秒
内存占用: 约 80-120 MB

天气 API 响应: 1-3 秒
AI 建议生成: 2-5 秒
数据库操作: < 100ms
3. 实验过程中遇到的问题和解决过程
问题1: PyQt6 多线程 UI 更新导致崩溃
问题描述: 在 WeatherFetcher 和 AdviceFetcher 等后台线程中直接更新 QLabel 等 UI 控件时,程序出现崩溃或无响应。错误提示:"QWidget: Must construct a QApplication before a QWidget" 或界面卡死。
原因分析: PyQt6 要求所有 UI 操作必须在主线程(GUI 线程)中执行。在子线程中直接修改 UI 违反了线程安全规则。
解决方案: 使用 PyQt6 的信号槽机制,通过 pyqtSignal 将数据从子线程传递到主线程:
class WeatherFetcher(QThread):
finished = pyqtSignal(dict) # 定义信号
error = pyqtSignal(str)
def run(self):
try:
data = weather_service.fetch_weather(city)
self.finished.emit(data) # 发射信号,而非直接更新 UI
except Exception as e:
self.error.emit(str(e))
# 在主窗口中连接信号
self.weather_fetcher = WeatherFetcher(city)
self.weather_fetcher.finished.connect(self.on_weather_loaded) # 槽函数在主线程执行
self.weather_fetcher.start()
def on_weather_loaded(self, data):
# 此方法在主线程中执行,可以安全更新 UI
self.weather_info_label.setText(f"温度: {data['temperature']}°C")
效果: 程序运行稳定,UI 响应流畅,不再出现线程安全问题。
问题2: APScheduler 定时任务精度不足
问题描述: 设置的日程提醒有时延迟几分钟才触发,甚至偶尔遗漏。
原因分析:
APScheduler 的 interval 触发器存在误差
仅依赖 scheduler 的一次性任务,若程序重启则任务丢失
时间判断逻辑不够精确
解决方案:
采用双重保障:每分钟轮询检查 + 一次性精确任务
扩大时间窗口判断(60 秒内均视为到期)
程序启动时重新注册所有未完成的提醒任务
# 每分钟轮询检查
self.scheduler.add_job(
func=self._check_reminders,
trigger='interval',
minutes=1,
id='check_reminders'
)
def _check_reminders(self):
now = datetime.now()
schedules = db_manager.get_today_schedules()
for schedule in schedules:
if schedule.get('is_completed', 0):
continue
reminder_time = schedule.get('reminder_time')
if not reminder_time:
continue
reminder_dt = datetime.strptime(reminder_time[:16], "%Y-%m-%d %H:%M")
# 60 秒窗口,避免遗漏
if reminder_dt <= now and (now - reminder_dt).total_seconds() < 60:
self._emit_reminder(schedule)
问题3: 界面布局在不同分辨率下显示异常
问题描述: 在高 DPI 屏幕或小尺寸屏幕上,部分控件重叠或溢出窗口边界。
原因分析:
使用了固定尺寸(setFixedSize)而非自适应布局
未考虑不同屏幕的 DPI 缩放
文本内容过长时未设置换行
解决方案:
优先使用布局管理器(QVBoxLayout、QHBoxLayout)而非绝对定位
设置最小/最大尺寸而非固定尺寸
启用文本自动换行(setWordWrap)
使用 stretch 因子灵活分配空间
# 原来固定尺寸容易重叠
label.setFixedSize(200, 50)
# 改为用布局管理器和stretch分配空间
layout = QVBoxLayout()
label = QLabel("长文本内容...")
label.setWordWrap(True) # 启用换行
layout.addWidget(label)
button = QPushButton("按钮")
button.setMinimumWidth(100) # 最小宽度
button.setMaximumWidth(200) # 最大宽度
layout.addWidget(button)
layout.addStretch() # 弹性空间
问题4: 删除操作缺乏二次确认导致误删
问题描述: 在日程列表或记账列表中点击删除时,没有确认提示,容易误删重要数据。
原因分析: 删除按钮直接执行删除操作,未给用户反悔机会。
解决方案: 实现通用的删除确认对话框,在所有删除操作前调用:
def show_delete_confirmation(parent, item_description="此项目"):
dialog = QDialog(parent)
dialog.setWindowTitle("确认删除")
dialog.setMinimumSize(320, 160)
layout = QVBoxLayout()
warning_icon = QLabel("⚠️")
warning_icon.setAlignment(Qt.AlignmentFlag.AlignCenter)
warning_icon.setStyleSheet("font-size: 32px;")
layout.addWidget(warning_icon)
message_label = QLabel(f"确定要删除{item_description}吗?\n此操作不可恢复!")
message_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(message_label)
btn_layout = QHBoxLayout()
confirm_btn = QPushButton("🗑️ 删除")
confirm_btn.setStyleSheet("background-color: #e74c3c; color: white;")
cancel_btn = QPushButton("❌ 取消")
result = False
def on_confirm():
nonlocal result
result = True
dialog.accept()
confirm_btn.clicked.connect(on_confirm)
cancel_btn.clicked.connect(dialog.reject)
btn_layout.addWidget(confirm_btn)
btn_layout.addWidget(cancel_btn)
layout.addLayout(btn_layout)
dialog.setLayout(layout)
dialog.exec()
return result
# 使用示例
if not show_delete_confirmation(self, "这个日程"):
return # 用户取消删除
db_manager.delete_schedule(schedule_id)
全课总结
本学期在王老师的教学带领下,我从零基础开始系统学习Python编程,一步步掌握了完整的基础语法与实操技能,能够独立编写代码、完成课程实验与小型项目。这一学期不仅积累了扎实的编程知识,也培养了基本的编程思维与自主学习能力,收获良多。
课程知识总结
本次课程内容由浅入深、循序渐进,涵盖Python基础语法、数据结构、流程控制、函数、面向对象、文件与异常处理以及各类实战应用,知识点覆盖面广、实用性强,让我建立了完整的Python知识框架。
在基础学习阶段,我了解了Python的语言特点:它是一门解释型、面向对象的高级语言,语法简洁、上手简单,相比C、C++更适合初学者快速入门。我熟练使用PyCharm、IDLE等开发工具,掌握了程序调试、报错排查、基础输入输出等操作,同时熟悉标识符、保留字、代码缩进规则,掌握了变量、常用数据类型、类型转换和基础运算符的使用方法。
在程序逻辑方面,我重点学习了顺序、分支、循环三种程序结构,熟练运用if条件判断、for和while循环语句编写代码。同时了解了死循环、数据溢出等常见问题,学会规避基础代码漏洞,养成规范命名、规范写代码的良好习惯。
我系统掌握了Python四种常用序列结构的特点与区别:列表可灵活增删改查、支持排序遍历;元组内容不可修改、稳定性强;字典以键值对存储数据、查询高效;集合元素唯一,主要用于去重。在字符串处理上,我掌握了切片、格式转换等基础操作,也初步接触正则表达式,能够完成简单的文本匹配、分割与清洗工作。
课程中期,我学习了多项核心进阶知识。通过函数的定义、参数传递与调用,我学会拆分代码功能,简化主程序,提高代码复用性。借助try-except-finally异常处理机制,我可以主动捕获程序报错,通过断点调试排查问题,提升代码稳定性。同时,我掌握了文件操作的基本流程,能够使用open、write、seek、close等函数完成文件的读写与管理。
面向对象编程是本学期的重点内容。我理解了“类是模板、对象是实例”的核心逻辑,能够用class定义类、用__init__方法初始化对象,掌握了封装、继承、多态三大特性。通过学习模块与包的应用,我了解到拆分程序模块可以有效降低项目开发难度,让代码结构更清晰、更易拓展。
在实战应用部分,我接触了Python的多种实用场景,包括网络爬虫、Socket网络通信、GUI界面编程、数据库操作和简易游戏开发。我学会使用爬虫库,了解robots协议和请求头的基本作用,能够完成简单的数据爬取与解析;掌握Socket通信基本原理,实现客户端与服务端的简单交互;通过PyQt5了解图形界面开发基础。此外,我也学会了Gitee、Github等代码平台的基础使用,能够完成代码上传与管理。
课程建议
增加分层课后练习。课程一周一节,间隔时间长,知识点容易遗忘。希望老师可以提供难度梯度的练习题,或者推荐合适的刷题平台,方便我们课后持续练习、巩固基础。
加强实验内容的前后衔接。建议后续实验融入旧知识,例如用面向对象思想重构前期基础代码,串联新旧知识点,避免学后面忘前面,形成连贯的知识体系。
增加实验展示和讲解环节。提交实验后可以让学生简单演示自己的代码思路,既能督促我们独立完成作业,减少对AI的依赖,也能互相交流学习、拓宽编程思路。
提供优秀实验范例参考。开放式实验自由度高,但初期没有参考标准,容易迷茫。希望可以展示往届优秀实验案例和报告模板,明确完成标准,同时强调原创性,更好地引导我们完成实验。
总结与展望
这一学期的Python学习,不仅让我掌握了扎实的编程技能,更培养了我的逻辑思维和自主探索能力。我并非只为学分学习这门课程,未来我会继续练习Python编程,把学到的知识运用到实际学习和项目实践中。
最后,再次感谢王老师一学期的悉心教导与付出!祝愿老师工作顺利、万事顺遂,我也希望今后能继续和老师交流学习,不断提升自己的编程能力。
其他
通过本次 SmartDaily 项目的开发,我获得了以下深刻的感悟和思考:
-
理论与实践的差距
课堂上学到的设计模式和架构理念,在实际应用中需要根据具体场景灵活调整。例如,单例模式虽然简单,但在多线程环境下需要特别注意线程安全;事件总线虽然能解耦模块,但过度使用会导致事件流向难以追踪。 -
用户体验至上
一个优秀的软件不仅要功能完善,更要注重用户体验。异步加载、友好提示、二次确认、错误降级等细节,看似微不足道,却直接影响用户的使用感受。在开发过程中,我不断站在用户角度思考:"如果我是用户,我希望如何操作?"这种思维转变让我意识到,技术开发最终是为了服务人。 -
健壮性比功能更重要
初期我过于追求功能丰富度,忽略了异常处理和边界情况。后来发现,程序崩溃一次带来的负面体验,远超过缺少一个功能的遗憾。现在我更加注重防御性编程,对每个可能失败的环节都做了充分的容错处理。 -
文档和注释的价值
在项目后期回顾代码时,我发现良好的注释和文档能极大提高维护效率。特别是对于复杂的业务逻辑(如定时提醒的时间窗口判断),清晰的注释能帮助自己和他人在几个月后快速理解代码意图。 -
持续学习的重要性
Python 生态庞大,新技术层出不穷。在本次项目中,我首次接触 PyQt6、APScheduler、httpx 等库,通过查阅官方文档、Stack Overflow 和社区教程,逐步掌握了它们的使用方法。这让我认识到,自主学习能力比记忆具体 API 更重要。 -
工程思维的养成
从最初的功能堆砌到后来的架构优化,我逐渐形成了系统性思维。开始时会先画流程图、设计类图,再动手编码;遇到 bug 时会系统地排查日志、分析堆栈,而非盲目试错。这种工程化的思维方式,是我在本实验中获得的最宝贵财富。
我希望能继续完善 SmartDaily,增加数据统计图表、语音提醒、云端同步等功能,并将其打包发布,让更多用户体验到这款小工具带来的便利,不断提升自己的软件工程能力。

浙公网安备 33010602011771号