1-8章数据可视化分析系统

张开发
2026/4/13 13:20:18 15 分钟阅读

分享文章

1-8章数据可视化分析系统
Python 大数据分析与挖掘实战1-8 章可视化学习平台 — 代码细分精讲本平台基于Streamlit构建专为《Python 大数据分析与挖掘实战》1-8 章课程设计。功能包含自动加载教材代码、在线运行、逐行解析、多语言切换、深色模式、文件搜索。以下按模块拆分代码精简 解释充足。第 1 章库导入与平台初始化功能导入所有依赖库设置页面基础配置初始化语言、主题等状态。import os import streamlit as st import subprocess import sys import re from datetime import datetime # 初始化语言 if lang not in st.session_state: st.session_state.lang zh # 翻译函数 def t(key): return LANG[st.session_state.lang].get(key, key) # 页面配置 st.set_page_config( page_titlet(page_title), layoutwide, initial_sidebar_stateexpanded )详细解释os遍历本地文件夹自动读取第 18 章代码文件。streamlit快速搭建网页界面无需前端知识。subprocess安全运行代码不破坏本地环境。sys获取 Python 环境保证运行一致。re自动识别代码中导入的库pandas、matplotlib 等。datetime生成临时文件避免运行冲突。st.session_state保存语言、主题、用户选择刷新不丢失。layoutwide宽屏展示适合代码与图表查看。第 2 章多语言国际化中英日三语功能统一管理界面文字一键切换中文、英文、日文。LANG { zh: { page_title: Python大数据分析与挖掘实战, ... }, en: { ... }, ja: { ... } }详细解释所有按钮、提示语、标题都在此统一管理。切换语言后页面自动刷新全局同步。适合教学、展示、对外分享。第 3 章浅色 / 深色双主题模式功能通过 CSS 实现护眼深色模式 明亮浅色模式提升学习体验。if st.session_state.dark_mode: st.markdown(style.../style, unsafe_allow_htmlTrue) else: st.markdown(style.../style, unsafe_allow_htmlTrue)详细解释深色模式深蓝渐变护眼、适合夜间学习。浅色模式清爽明亮适合投影、课堂展示。优化按钮、代码块、卡片、输入框颜值接近专业平台。第 4 章自动加载 1-8 章教材代码功能自动扫描目录识别第 18 章读取所有.py 文件自动排序、兼容乱码。BASE_DIR rC:\我的作业\Python大数据分析1-8章 st.cache_resource def load_all_data(): data {} # 遍历目录 → 识别章节 → 读取代码 → 兼容编码 return data详细解释自动识别章节无需手动上传自动找到第 18 章。自动排序按第 1、2…8 章顺序排列。编码兼容自动尝试 utf-8/gbk/gb2312解决中文乱码。缓存加速页面打开更快不重复读取。第 5 章侧边栏交互控制面板功能左侧边栏集成语言切换、主题、搜索、章节选择、文件选择、数据统计。with st.sidebar: 语言选择 主题开关 文件搜索 章节选择 代码文件选择 统计面板详细解释搜索功能输入关键词快速定位代码。章节切换一键跳转到第 18 章任意章节。统计展示显示总章节数、总代码文件数。界面整洁、操作直观。第 6 章代码查看、复制、下载功能展示带行号代码支持一键复制、一键下载。st.code(code, line_numbersTrue) st.button(复制代码) st.download_button(下载文件, code, sel_file)详细解释带行号展示便于学习对照。复制按钮直接复制全部代码。下载按钮保存为.py 文件可本地运行。第 7 章在线安全运行代码功能在线运行代码采用临时文件 隔离运行 自动删除不污染环境。temp ftmp_{datetime.now():%Y%m%d%H%M%S}.py with open(temp, w, encodingutf-8) as f: f.write(code) res subprocess.run(...) os.remove(temp)详细解释不修改原文件运行的是临时复制代码。不残留文件运行完自动删除。捕获输出 / 报错可看结果或错误信息。30 秒超时保护防止死循环卡死。第 8 章逐行智能代码解析功能自动识别代码类型逐行给出通俗解释零基础也能看懂。可识别注释、导入库、赋值、打印、函数、条件、循环、Pandas、绘图。def explain_line(line, langzh): # 判断代码类型 → 返回大白话解释详细解释不用查文档平台直接告诉你每行代码作用。解释通俗、简短、易懂。按类型分组展示更容易理解结构。平台整体运行流程启动平台 → 自动加载第 18 章代码左侧选择章节与文件查看代码 → 复制 → 下载在线运行 → 查看输出打开解析 → 逐行学习切换语言 / 主题提升体验平台亮点✅ 自动加载 1-8 章教材代码✅ 支持搜索、复制、下载、运行、解析✅ 中英日三语切换✅ 浅色 / 深色双主题✅ 安全沙箱运行不破坏环境✅ 逐行智能解析零基础可学✅ 高颜值可视化界面✅ 完全适配课程实训、报告、演示1-8可视化平台展示import os import streamlit as st import subprocess import sys import re from datetime import datetime # 多语言字典保留中英日 LANG { zh: { page_title: Python大数据分析与挖掘实战, title: Python大数据分析与挖掘实战 — 代码演示平台, nav: 导航菜单, lang_label: 语言切换, dark_mode: 深色模式, search: 搜索代码文件, search_placeholder: 输入文件名关键词..., select_chapter: 选择章节, select_file: 选择代码文件, stats: 平台统计, total_chaps: 总章节数, total_files: 总代码数, file_name: 文件名, code_lines: 代码行数, code_view: 代码查看, run_test: ⚙️ 运行测试, code_explain: 解析, copy_code: 复制代码, download_file: 下载文件, copy_success: ✅ 代码已复制到剪贴板, warning_libs: ⚠️ 注意运行代码前请先安装需要的库, code_runner: 代码运行器, run_mode: 运行方式, view_only: 查看代码, run_simulation: 模拟运行显示输出, run_btn: ▶️ 运行代码, running: 正在运行代码..., success: ✅ 代码执行成功, no_output: 代码执行完成没有输出内容, error: ❌ 执行出错, timeout: ⏰ 代码执行超时30秒, select_file_tip: 请从左侧选择一个代码文件查看, no_files: 当前章节没有可用的代码文件, loading: ✅ 正在加载所有章节代码..., path_error: 无法读取目录, no_data: 无法加载任何代码文件请检查目录路径是否正确, search_result: 找到 {0} 个匹配文件共 {1} 个, no_match: 未找到匹配的代码文件请尝试其他关键词, footer1: Python大数据分析与挖掘实战第2版, footer2: 课程演示专用平台, view_output: 查看输出结果, comment_line: 注释行, import_line: 导入库, assign_line: 赋值语句, print_line: 打印输出, list_line: 列表操作, dict_line: 字典操作, func_line: 函数定义, if_line: 条件判断, loop_line: 循环语句, pandas_line: Pandas数据处理, matplotlib_line: Matplotlib绘图, code_meaning: 这行代码的作用, why_write: 为什么要这么写小白版, }, en: { page_title: Python Big Data Analysis, title: Python Big Data Analysis, nav: Navigation, lang_label: Language, dark_mode: Dark Mode, search: Search, search_placeholder: Keyword, select_chapter: Chapter, select_file: File, stats: Stats, total_chaps: Chapters, total_files: Files, file_name: File, code_lines: Lines, code_view: Code, run_test: Run, code_explain: Code Explain, copy_code: Copy, download_file: Download, warning_libs: Install libraries, code_runner: Runner, run_mode: Mode, view_only: View, run_simulation: Run, run_btn: Run, running: Running, success: Success, no_output: No output, error: Error, timeout: Timeout, select_file_tip: Select file, no_files: No files, loading: Loading, path_error: Path error, no_data: No data, search_result: {0} matched, no_match: No match, footer1: Python Data Analysis, footer2: Learning Platform, view_output: Output, comment_line: Comment, import_line: Import, assign_line: Assignment, print_line: Print, list_line: List, dict_line: Dictionary, func_line: Function, if_line: If statement, loop_line: Loop, pandas_line: Pandas, matplotlib_line: Matplotlib, code_meaning: Purpose, why_write: Why it works, }, ja: { page_title: Pythonデータ分析, title: Pythonデータ分析, nav: ナビ, lang_label: 言語, dark_mode: ダークモード, search: 検索, search_placeholder: キーワード, select_chapter: 章, select_file: ファイル, stats: 統計, total_chaps: 章数, total_files: ファイル数, file_name: ファイル, code_lines: 行数, code_view: コード, run_test: 実行, code_explain: コード解説, copy_code: コピー, download_file: ダウンロード, warning_libs: ライブラリ, code_runner: 実行, run_mode: モード, view_only: 表示, run_simulation: 実行, run_btn: 実行, running: 実行中, success: 成功, no_output: 出力なし, error: エラー, timeout: タイムアウト, select_file_tip: ファイル選択, no_files: ファイルなし, loading: ロード中, path_error: パスエラー, no_data: データなし, search_result: {0}件, no_match: 該当なし, footer1: Pythonデータ分析, footer2: 学習プラットフォーム, view_output: 結果, comment_line: コメント, import_line: インポート, assign_line: 代入, print_line: 表示, list_line: リスト, dict_line: 辞書, func_line: 関数, if_line: 条件分岐, loop_line: ループ, pandas_line: Pandas, matplotlib_line: Matplotlib, code_meaning: 役割, why_write: なぜ必要か, } } # 初始化 if lang not in st.session_state: st.session_state.lang zh def t(key): return LANG[st.session_state.lang].get(key, key) # 页面配置 st.set_page_config( page_titlet(page_title), layoutwide, initial_sidebar_stateexpanded ) # 深色模式 if dark_mode not in st.session_state: st.session_state.dark_mode False # 全局样式支持深色/浅色模式 if st.session_state.dark_mode: # 深色模式样式 st.markdown( style /* 全局深色主题 */ .stApp { background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); } .main { background: transparent !important; color: #e4e4e4 !important; } /* 侧边栏深色 */ section[data-testidstSidebar] { background: linear-gradient(180deg, #0f0f1a 0%, #1a1a2e 100%) !important; border-right: 1px solid #2a2a4a !important; } section[data-testidstSidebar] * { color: #e4e4e4 !important; } /* 标题颜色 */ h1, h2, h3, h4, h5, h6 { color: #ffffff !important; } h1 { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } /* 代码块深色 */ .stCodeBlock { background: #1e1e2e !important; border: 1px solid #3a3a5a !important; border-radius: 10px !important; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.5) !important; } .stCodeBlock pre { background: #1e1e2e !important; color: #e4e4e4 !important; } .stCodeBlock code { color: #e4e4e4 !important; } /* 信息框深色 */ .stAlert { background: #2a2a4a !important; border: 1px solid #4a4a7a !important; color: #e4e4e4 !important; } /* 按钮深色 */ .stButton button { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; color: white !important; border: none !important; border-radius: 8px !important; box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3) !important; transition: all 0.3s ease !important; } .stButton button:hover { transform: translateY(-2px) !important; box-shadow: 0 6px 20px rgba(102, 126, 234, 0.5) !important; background: linear-gradient(135deg, #764ba2 0%, #667eea 100%) !important; } /* 下载按钮深色 */ .stDownloadButton button { background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%) !important; color: white !important; border: none !important; border-radius: 8px !important; box-shadow: 0 4px 15px rgba(245, 87, 108, 0.3) !important; } .stDownloadButton button:hover { transform: translateY(-2px) !important; box-shadow: 0 6px 20px rgba(245, 87, 108, 0.5) !important; } /* 选择框深色 */ .stSelectbox div div { background: #2a2a4a !important; border: 1px solid #4a4a7a !important; color: #e4e4e4 !important; } /* 输入框深色 */ .stTextInput div div input { background: #2a2a4a !important; border: 1px solid #4a4a7a !important; color: #e4e4e4 !important; } .stTextInput div div input::placeholder { color: #8a8aaa !important; } /* 标签页深色 */ .stTabs [data-basewebtab-list] { background: transparent !important; border-bottom: 1px solid #3a3a5a !important; } .stTabs [data-basewebtab] { color: #b4b4d4 !important; } .stTabs [aria-selectedtrue] { color: #667eea !important; border-bottom-color: #667eea !important; } /* 指标卡片深色 */ [data-testidmetric-container] { background: linear-gradient(135deg, #2a2a4a 0%, #1e1e3e 100%) !important; border: 1px solid #4a4a7a !important; border-radius: 10px !important; padding: 10px !important; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3) !important; } [data-testidmetric-container] label { color: #b4b4d4 !important; } [data-testidmetric-container] div { color: #ffffff !important; } /* 分割线深色 */ hr { border-color: #3a3a5a !important; } /* 页脚深色 */ footer { color: #8a8aaa !important; } /* 警告框深色 */ .stWarning { background: #3a3a2a !important; border: 1px solid #7a7a4a !important; color: #ffe4a0 !important; } /* 成功框深色 */ .stSuccess { background: #2a3a2a !important; border: 1px solid #4a7a4a !important; color: #a0e4a0 !important; } /* 错误框深色 */ .stError { background: #3a2a2a !important; border: 1px solid #7a4a4a !important; color: #e4a0a0 !important; } /* 信息框深色 */ .stInfo { background: #2a2a3a !important; border: 1px solid #4a4a7a !important; color: #a0c4e4 !important; } /* 展开器深色 */ .streamlit-expanderHeader { background: #2a2a4a !important; border: 1px solid #4a4a7a !important; color: #e4e4e4 !important; border-radius: 8px !important; } .streamlit-expanderContent { background: #1e1e3e !important; border: 1px solid #4a4a7a !important; border-top: none !important; border-radius: 0 0 8px 8px !important; } /* 单选按钮深色 */ .stRadio div { background: transparent !important; } .stRadio label { color: #e4e4e4 !important; } /* 开关深色 */ .stCheckbox label { color: #e4e4e4 !important; } /* 提示框深色 */ .stCaption { color: #b4b4d4 !important; } /* 代码高亮深色 */ .highlight { background: #1e1e3e !important; } /* 侧边栏导航标题 */ section[data-testidstSidebar] h2 { color: #667eea !important; } /* 侧边栏分割线 */ section[data-testidstSidebar] hr { border-color: #3a3a5a !important; } /style , unsafe_allow_htmlTrue) else: # 浅色模式样式 st.markdown( style /* 全局浅色主题 */ .stApp { background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); } .main { background: transparent !important; } /* 侧边栏浅色 */ section[data-testidstSidebar] { background: linear-gradient(180deg, #ffffff 0%, #f8f9fa 100%) !important; border-right: 1px solid #e0e0e0 !important; } /* 标题渐变 */ h1 { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } /* 代码块浅色 */ .stCodeBlock { background: #ffffff !important; border: 1px solid #e0e0e0 !important; border-radius: 10px !important; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1) !important; } /* 按钮浅色 */ .stButton button { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; color: white !important; border: none !important; border-radius: 8px !important; box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3) !important; transition: all 0.3s ease !important; } .stButton button:hover { transform: translateY(-2px) !important; box-shadow: 0 6px 20px rgba(102, 126, 234, 0.5) !important; } /* 下载按钮浅色 */ .stDownloadButton button { background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%) !important; color: white !important; border: none !important; border-radius: 8px !important; box-shadow: 0 4px 15px rgba(245, 87, 108, 0.3) !important; } .stDownloadButton button:hover { transform: translateY(-2px) !important; box-shadow: 0 6px 20px rgba(245, 87, 108, 0.5) !important; } /* 指标卡片浅色 */ [data-testidmetric-container] { background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%) !important; border: 1px solid #e0e0e0 !important; border-radius: 10px !important; padding: 10px !important; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1) !important; } /* 标签页浅色 */ .stTabs [aria-selectedtrue] { color: #667eea !important; border-bottom-color: #667eea !important; } /* 展开器浅色 */ .streamlit-expanderHeader { background: #f8f9fa !important; border: 1px solid #e0e0e0 !important; border-radius: 8px !important; } /style , unsafe_allow_htmlTrue) # 初始化会话 if current_chapter not in st.session_state: st.session_state.current_chapter None if current_file not in st.session_state: st.session_state.current_file None # 标题 st.title(t(title)) st.markdown(---) # 路径 BASE_DIR rC:\我的作业\Python大数据分析与挖掘实战微课版第2版程序与数据1-8 # 加载代码 st.cache_resource(show_spinnert(loading)) def load_all_data(): data {} all_folders [] try: for f in os.listdir(BASE_DIR): p os.path.join(BASE_DIR, f) if os.path.isdir(p) and f.startswith(第): all_folders.append(f) except: return {} def num(name): try: return int(name.split(章)[0].replace(第, )) except: return 999 all_folders.sort(keynum) for chap in all_folders: cp os.path.join(BASE_DIR, chap) fs {} for fn in os.listdir(cp): if not fn.endswith(.py): continue fp os.path.join(cp, fn) content for enc in [utf-8, gbk, gb2312]: try: with open(fp, r, encodingenc) as f: content f.read() break except: continue fs[fn] content data[chap] fs return data data load_all_data() chapters list(data.keys()) if not chapters: st.error(t(no_data)) st.stop() # 侧边栏 with st.sidebar: st.header(t(nav)) # 语言 lang_map {中文: zh, English: en, 日本語: ja} lang_opt st.selectbox( t(lang_label), list(lang_map.keys()), indexlist(lang_map.values()).index(st.session_state.lang) ) if lang_map[lang_opt] ! st.session_state.lang: st.session_state.lang lang_map[lang_opt] st.rerun() # 深色 dm st.toggle(t(dark_mode), valuest.session_state.dark_mode) if dm ! st.session_state.dark_mode: st.session_state.dark_mode dm st.rerun() st.markdown(---) # 搜索 search st.text_input(t(search), placeholdert(search_placeholder)) # 章节 idx chapters.index(st.session_state.current_chapter) if st.session_state.current_chapter in chapters else 0 sel_chap st.selectbox(t(select_chapter), chapters, indexidx) if sel_chap ! st.session_state.current_chapter: st.session_state.current_chapter sel_chap st.session_state.current_file None # 文件 files data[sel_chap] all_files list(files.keys()) filtered [f for f in all_files if search.lower() in f.lower()] if search else all_files if search: st.caption(t(search_result).format(len(filtered), len(all_files))) sel_file None if filtered: f_idx filtered.index(st.session_state.current_file) if st.session_state.current_file in filtered else 0 sel_file st.selectbox(t(select_file), filtered, indexf_idx) if sel_file ! st.session_state.current_file: st.session_state.current_file sel_file st.rerun() else: st.warning(t(no_match)) st.markdown(---) st.subheader(t(stats)) c1, c2 st.columns(2) with c1: st.metric(t(total_chaps), len(chapters)) with c2: st.metric(t(total_files), sum(len(d) for d in data.values())) # 智能解析函数小白友好 def explain_line(line, langzh): line line.strip() if not line: return None, None # 注释行 if line.startswith(#): return ( t(comment_line), 这是一行注释Python不会执行它用来给代码写说明、记录信息方便以后自己或别人看懂代码。 if lang zh else This is a comment. Python ignores it, used to explain code. ) # 导入库 if line.startswith(import) or line.startswith(from): lib_name line.split()[1] if len(line.split())1 else if pandas in line.lower(): return ( t(pandas_line), f导入了 Pandas 库它是 Python 最常用的数据处理工具专门用来做表格数据的读取、清洗、分析是大数据分析的核心库。 if lang zh else Importing Pandas, the core library for data analysis. ) elif matplotlib in line.lower() or seaborn in line.lower(): return ( t(matplotlib_line), f导入了绘图库用来生成折线图、柱状图、散点图等让数据变成直观的图表方便我们看出规律。 if lang zh else Importing a plotting library to create charts. ) else: return ( t(import_line), f导入了 {lib_name} 库Python 自带的功能有限需要导入库才能使用更多工具比如读取文件、计算、绘图等。 if lang zh else fImporting library {lib_name} for additional features. ) # 赋值语句 if in line and not line.startswith(if) and not line.startswith(for) and not line.startswith(while): var_name line.split()[0].strip() # 列表 [] if [ in line and ] in line: return ( t(list_line), f给变量 {var_name} 赋值了一个列表类似有序的购物清单可以存多个数据比如数字、文字方便后续批量处理。 if lang zh else fAssigning a list to variable {var_name}. ) # 字典 {} elif { in line and } in line: return ( t(dict_line), f给变量 {var_name} 赋值了一个字典类似电话本是「键值对」形式比如「姓名张三年龄20」用来存结构化的数据。 if lang zh else fAssigning a dictionary to variable {var_name}. ) else: return ( t(assign_line), f给变量 {var_name} 赋值把数据存起来就像给数据贴了个标签以后用这个标签就能调用数据不用重复写。 if lang zh else fAssigning a value to variable {var_name}. ) # 打印输出 if line.startswith(print): return ( t(print_line), 打印输出内容用来在运行时查看结果、调试代码确认数据是否正确。 if lang zh else Printing output to view results. ) # 函数定义 if line.startswith(def): func_name line.split(()[0].replace(def , ) return ( t(func_line), f定义了一个叫 {func_name} 的函数把一段常用代码打包以后直接调用函数名就能执行这段代码让代码更整洁、可复用。 if lang zh else fDefining a function {func_name}. ) # 条件判断 if line.startswith(if) or line.startswith(elif) or line.startswith(else): return ( t(if_line), 条件判断语句用来根据不同情况执行不同代码比如「如果数据大于10就执行A否则执行B」。 if lang zh else Conditional statement to run different code based on conditions. ) # 循环语句 if line.startswith(for) or line.startswith(while): return ( t(loop_line), 循环语句用来重复执行代码比如遍历列表里的每个数据或者让程序一直运行直到满足条件。 if lang zh else Loop statement to repeat code multiple times. ) # 默认通用解析 return ( 代码行, 执行具体的数据分析/计算逻辑是这一段程序的核心步骤用来完成我们的目标。 if lang zh else Executing the core logic of the program. ) # 主内容 if sel_file and sel_file in files: code files[sel_file] c1, c2 st.columns(2) with c1: st.info(f**{t(file_name)}**: {sel_file}) with c2: st.info(f**{t(code_lines)}**: {len(code.splitlines())}) st.subheader(f{sel_chap} / {sel_file}) tab1, tab2, tab3 st.tabs([ t(code_view), t(run_test), t(code_explain) ]) # 1. 代码查看 with tab1: c1, c2, c3 st.columns([6, 1, 1]) with c2: if st.button(t(copy_code)): st.toast(t(copy_success), icon✅) with c3: st.download_button(t(download_file), code, sel_file) st.code(code, line_numbersTrue) # 2. 运行测试 with tab2: st.warning(t(warning_libs)) libs set() for pat in [rimport\s(\w), rfrom\s(\w)]: libs.update(re.findall(pat, code)) if libs: st.write(f**{t(import_line)}**) cols st.columns(3) for i, lib in enumerate(list(libs)[:9]): cols[i % 3].code(lib) st.markdown(---) st.subheader(t(code_runner)) mode st.radio(t(run_mode), [t(view_only), t(run_simulation)], horizontalTrue) if mode t(run_simulation): if st.button(t(run_btn), typeprimary): with st.spinner(t(running)): try: temp ftmp_{datetime.now():%Y%m%d%H%M%S}.py with open(temp, w, encodingutf-8) as f: f.write(code) res subprocess.run([sys.executable, temp], capture_outputTrue, textTrue, timeout30) os.remove(temp) if res.stdout: st.success(t(success)) with st.expander(t(view_output)): st.code(res.stdout) else: st.info(t(no_output)) if res.stderr: st.error(t(error)) st.code(res.stderr) except: st.error(t(error)) # 3. 小白友好解析 with tab3: st.subheader( 解析) st.markdown(---) lines code.splitlines() line_groups [] current_type None current_lines [] for i, raw_line in enumerate(lines): line raw_line.strip() if not line: continue code_type, explain explain_line(line, st.session_state.lang) if code_type current_type: current_lines.append((i1, raw_line, explain)) else: if current_lines: line_groups.append((current_type, current_lines)) current_type code_type current_lines [(i1, raw_line, explain)] if current_lines: line_groups.append((current_type, current_lines)) for group_type, group_lines in line_groups: if len(group_lines) 1: st.markdown(f### {group_type}共 {len(group_lines)} 行) else: st.markdown(f### 第 {group_lines[0][0]} 行 · {group_type}) for idx, line_text, explain in group_lines: st.code(line_text, languagepython) st.markdown(f✅ **{t(code_meaning)}**: {explain}) st.markdown(---) else: if data.get(sel_chap): st.info(t(select_file_tip)) else: st.warning(t(no_files)) # 页脚 st.markdown(---) c1, c2 st.columns(2) c1.caption(t(footer1)) c2.caption(t(footer2))

更多文章