Python题库doc文档清洗与自动化练习全指南
简介这是一份Python编程题库文档面向正在学习Python基础语法、准备期中期末或等级考试的学生也可用于教师出题参考。内容由选择题和程序填空两大板块组成选择题覆盖逻辑运算与布尔值、列表max取最大值、变量内存管理、input/print区分、浮点除法、区间表达式、相等关系写法等高频考点程序填空部分则涉及蒙特卡洛方法求圆周率、奇偶校验码判断、滴滴快车分段计费规则等实际场景应用题并附有部分答案与解析。资源为单独一个doc文件体积约220KB便于直接打开浏览、筛选或打印练习。文档整合了Python核心知识点的典型题目与配套解析读者可对照答案解析逐步理解常见易错点和算法实现思路适合用于考前突击、自测巩固和日常课堂训练。已有269人学习使用对希望系统梳理Python基础的初学者有较强的参考价值。1. 拿到“Python题库.doc”之后先别急着做题很多初学者或培训讲师电脑里都躺着这样一个文件别人传的、网盘下的或者自己攒了好几年的“编程(完整版)Python题库.doc”。文件不小目录看着也挺全从基础语法到文件操作、异常处理、面向对象甚至网络编程都有覆盖。但真打开准备练的时候问题立刻就来了——格式乱、代码缩进全没了、中文引号变成乱码复制一段题目的代码进解释器直接报错。我见过太多人卡在这一步就放弃了转头去刷在线网站回头又说文档题库没用。这篇文章不打算夸这份题库有多好也不替它背书。我想说的是一个 .doc 格式的 Python 题库到底怎么处理才能变成真正能用来刷题、备课、甚至二次出题的东西。核心就三件事——把文档转成干净可用的格式把题目按质量筛一遍再让它能高效地进到你的练习闭环里。这套流程我自己用在不同来源的题库上反复做过每一步都有坑也有对应的解决办法。新手能照着操作熟手可以直接跳到格式转换和自动化抽题的部分看参数。2. 先把 .doc 转成 .docx 或 .md为什么这一步不能省2.1 .doc 老格式的三大坑乱码、缩进丢失、不可批量处理.doc 是微软老一代的二进制格式和 .docx 的 OpenXML 结构完全不同。它最大的问题是“文本和格式揉在一起”解析难度大很多现代的文本处理工具对它支持都不好。具体到 Python 题库这种场景三个坑最明显。第一个坑是编码。老 .doc 文件默认用 ANSI 编码保存里面如果带了中文全角引号、长破折号这类字符用 Python 的 open() 直接读经常报 UnicodeDecodeError或者读出来是一堆 “锟斤拷”。第二个坑是代码缩进。Python 代码靠缩进区分块级结构但 .doc 里的缩进很多是用制表符、全角空格或者 Word 的自动编号混合实现的复制到 IDE 里要么全部顶格要么混进奇怪字符。第三个坑是批量操作困难。你想把题库按章节拆开、或者提取所有代码块用 .doc 就得依赖 win32com 调起 Word 进程慢且容易卡死。所以拿到文件第一步先把它转成 .docx。这不是玄学而是 .docx 本质是一个 zip 包里面是 XML 文本Python 有成熟的 python-docx 库可以直接解析数据是结构化的代码块和普通段落可以区分处理。2.2 用 LibreOffice 批量转格式最稳的命令行方案我一般不用 Word 自带的“另存为”因为没法批量操作几十个文件。常见做法是装一个 LibreOffice然后用它的 headless 模式在命令行批量转换。LibreOffice 对 .doc 的兼容性做得比较成熟转出来的 .docx 基本不乱码。# 批量把当前目录下所有 .doc 转成 .docx soffice --headless --convert-to docx --outdir ./converted ./source/*.doc这段命令的逻辑很直白--headless表示不启动界面--convert-to docx指定输出格式--outdir指定输出目录。./source/*.doc是通配符一次处理文件夹里所有 .doc 文件。如果你只想转一个文件就把最后一个参数改成具体文件名。参数说明注意soffice命令在 Windows 上一般叫soffice.exe如果提示找不到命令检查 LibreOffice 的安装路径有没有加进系统环境变量。另外LibreOffice 转出来的 .docx 可能会把原来用自动编号的列标题转成纯文本数字这个不影响后续使用。转换完成后打开几个文件抽查一下重点看代码段是不是还保持缩进。如果文件实在太大转 .docx 之后打开还是卡还有一个更激进的办法——直接转成纯文本 .md 格式。这样做会丢失所有加粗、标题样式但好处是所有内容变成纯文本缩进问题反而好处理了。2.3 用 python-docx 抽代码块把答案和题目切开转成 .docx 之后就可以用 python-docx 做更精细的操作。一个很常见的需求是把题目和答案拆开。很多题库文档的结构是“题目描述下面紧跟答案代码”或者“题目标题用加粗答案代码用等宽字体”。我们要做的就是识别这些特征然后分开保存。# 读取 docx按样式拆分题目和答案 from docx import Document import re doc Document(converted/编程(完整版)Python题库.docx) questions [] answers [] for para in doc.paragraphs: text para.text.strip() if not text: continue # 判断题型题目一般以数字加顿号或点开头 if re.match(r^\d[.、], text): questions.append(text) continue # 判断是否为代码块以空格或 tab 开头或者包含常见关键字 if text.startswith(( , \t)) or (def in text or print( in text or import in text): answers.append(text) continue # 其他正文段落归入题目区 questions.append(text) print(f提取到 {len(questions)} 段题目描述{len(answers)} 段疑似代码块)逻辑说明这段代码先把段落按空白过滤然后用正则判断是否以数字开头是就认为是题目标题。代码块的判断用的是“以空格开头或包含关键字”的规则实际效果对大部分题库能达到 70%~80% 的准确率。为什么不是100%因为有些题库的代码块并没有统一的前缀有的用三个空格缩进有的用制表符有的代码里根本没有def和print。更稳的方案是打开 .docx 看段落对象里的style.name。如果题库是用 Word 排版过的题目可能是List Paragraph样式代码是Normal且带左缩进。这时判断条件改成para.paragraph_format.left_indent是否为特定值识别率会高很多。你在自己的文档上可以先跑一版统计看看缩进用的到底是空格还是 tab再决定判断规则。3. 让题库“能练起来”清洗题目和代码的五个标准动作3.1 统一代码缩进把全角空格和制表符全部换掉从 Word 里复制出来的代码最致命的就是缩进字符混杂。Python 解释器对缩进极其敏感一个全角空格混进去就会报IndentationError: unindent does not match any outer indentation level。清洗这一步的目标只有一个让每一段代码变成能用解释器直接跑的状态。# 清洗单个代码块 def clean_code_block(code_lines): cleaned [] for line in code_lines: # 把全角空格替换成普通空格 line line.replace(\u3000, ) # 把制表符替换成四个空格 line line.replace(\t, ) # 去掉行尾多余空白 line line.rstrip() cleaned.append(line) return \n.join(cleaned) raw_code def hello(): \tprint(你好) \u3000\u3000return 1 print(clean_code_block(raw_code.split(\n)))逻辑说明\u3000是全角空格的 Unicode 编码这个字符在中文输入法下极易混入代码。替换规则是统一成普通半角空格再把制表符展开成四个空格。为什么要展开成四个空格而不是一个 tab因为绝大多数 Python 编辑器默认把 tab 显示成 4 个空格但如果代码里混用 tab 和空格解释器会直接报错。统一成空格能彻底避开这个问题。参数说明如果原始题库用的是 2 空格缩进风格把 改成 就行。但 Python 官方 PEP 8 推荐 4 空格建议清洗时统一按 4 空格来。另外注意字符串里的\t别被误替换——如果你在代码里写了print(a\tb)这个\t在字符串常量里不应该动它。但上面的逻辑没有区分字符串内和行首的 tab这是一个简化处理。严谨一点的做法是用 tokenize 模块去判断不过对题库练习场景来说误伤的概率很低手工修一下也快。3.2 处理中文引号与编码问题一道经典的“乱码”题目中文题库里最常见的问题是代码里的字符串用了中文引号比如print(“hello”)。这在 Word 里看起来很正常但 Python 解释器只认 ASCII 引号直接运行就是SyntaxError: invalid character “ (U201C)。# 把全角引号替换成半角引号 import re def fix_chinese_quotes(code_text): # 只处理成对出现的引号避免误伤字符串内容 # 把左双引号替换为 ASCII 双引号 code_text code_text.replace(“, ) # 把右双引号替换为 ASCII 双引号 code_text code_text.replace(”, ) # 单引号同理 code_text code_text.replace(‘, ) code_text code_text.replace(’, ) return code_text sample print(“hello world”) print(fix_chinese_quotes(sample))逻辑说明这个规则是暴力替换风险在于如果字符串内容里故意用了全角引号来表达某种文本效果会被一起改掉。但对题库代码来说全角引号基本都是键盘误输入直接替换是收益最高的做法。真正注意的地方是注释里的内容不需要改改了也不影响运行所以暴力替换的副作用可以接受。更进一步如果整个文件读进来出现UnicodeDecodeError多半是编码没对上。常见做法是强制用 GBK 或 UTF-8 读取失败就换另一种# 自动检测编码并读取文件 def read_text_smart(filepath): for enc in [utf-8, gbk, gb2312, latin-1]: try: with open(filepath, r, encodingenc) as f: return f.read() except UnicodeDecodeError: continue raise RuntimeError(f文件 {filepath} 无法用常见编码解码)这个函数的逻辑是逐个尝试编码方案latin-1是最后兜底它不会报错但读出来是乱码。用这个函数能快速定位文件真实的保存编码。我自己处理过的题库里GBK 编码的 .txt 文件占了相当比例尤其是直接从 Windows 老机器上拷出来的。3.3 代码块切分解决“题干里混着代码”的边界问题整个题库清洗中最费时间的是切分。很多题目的结构是3. 编写一个函数计算列表的平均值 def average(lst): return sum(lst) / len(lst)但如果题干里也出现了“例如print(1)”就会被误判成代码块。所以要按“连续代码行”来切分而不是按单行判断。# 按连续行切分代码块 def split_code_blocks(lines): blocks [] current [] for line in lines: # 空行可能出现在代码中间也可能是段落分界 if line.strip() : if current: blocks.append(current) current [] else: # 行首有缩进或者是 Python 语法关键字开头 if line.startswith(( , \t)) or line.startswith((def , class , import , from , print(, if , for , while )): current.append(line) else: if current: blocks.append(current) current [] if current: blocks.append(current) return blocks逻辑说明split_code_blocks把文本按行读入遇到空行或连续的非代码行就认为一个代码块结束。好处是可以在块级别做后续处理。比如你筛选“某一段代码能否单独运行”只需要把blocks里的每一项写进临时文件再执行。这里有个常见误区不要试图用正则一行匹配所有代码行因为题库排版总是会给你惊喜。比如有的题把代码用表格框起来、有的代码带有行号前缀1.、有的代码和题干之间没有空行。遇到这种手工补一个空行比写自动化规则更省时间。清洗工具处理掉 80% 的活剩下 20% 用手工是效率最高的配比。3.4 用 py_compile 做语法校验一分钟找出所有还不能跑的代码清洗之后的代码块是不是真的能跑用py_compile可以快速做整体校验。这个模块不执行代码只编译检查语法速度很快。# 批量语法校验 import py_compile import tempfile import os def validate_code_blocks(blocks): valid_count 0 syntax_errors [] for idx, block in enumerate(blocks): # 每个代码块写入临时文件 with tempfile.NamedTemporaryFile(modew, suffix.py, deleteFalse, encodingutf-8) as f: f.write(block) temp_path f.name try: py_compile.compile(temp_path, doraiseTrue) valid_count 1 except py_compile.PyCompileError as e: syntax_errors.append((idx, str(e))) finally: os.unlink(temp_path) print(f校验 {len(blocks)} 个代码块通过 {valid_count} 个失败 {len(syntax_errors)} 个) return syntax_errors逻辑说明每个代码块独立写盘再编译目的是模拟“单独运行”的场景。因为题库里有些代码是片段需要依赖前面的上下文变量才能跑这类题py_compile是查不出来的它只能查语法。校验结果里失败的代码块基本就是题目本身写错了、排版乱了或者是答案里带了省略号。这些就是需要人工处理的少数派。参数说明doraiseTrue表示有错就抛异常而不是打警告这样方便统计。suffix.py保证文件后缀是 .py否则 py_compile 会拒绝编译。这里还会踩一个坑Windows 的临时目录可能有权限限制导致NamedTemporaryFile删除失败如果报 PermissionError把os.unlink改成os.remove并加 try 处理就行。4. 判断这份题库值不值得深挖三类题目分级法4.1 值得逐题练的题目特征清洗完之后第一件事不是急着刷题而是先对题库做“质量分级”。我处理过几份不同的 Python 题库文档发现里面的题目质量差异极大。有些题是典型的“为了出题而出题”比如无意义地让你计算一个很大的阶乘有些题则非常贴合面试和实战比如让你封装一个带错误处理的文件读取函数。值得优先做的题目通常有这几个特征题目描述里给出了明确的输入输出示例比如“输入 [1, 2, 3]输出 6”这种题目的结果是可验证的做完能立刻知道对错。这是知根知底的题。题目涉及的知识点组合不单一。比如同时考函数定义、循环和列表操作比单纯考for i in range(10)更有价值。有边界条件的暗示比如“假设列表可能为空”“输入可能是负数”。这类题会让你养成考虑边界情况的习惯往小了说是刷题往大了说是工程习惯。反过来如果题目描述只有一句话“请编写一个函数”没有任何输入输出说明这种题做起来非常难受——你都不知道答案长什么样才算对。这类题我建议先跳过等整本题库做完一遍再回头补。4.2 用难度和知识点打标签给题库做目录和索引题库文档里一般自带目录但那只是章节分类比如“第3章 循环语句”。真要用来复习和练习最好自己做一套标签。我给题库打标签时常用的维度有两个难度入门 / 进阶 / 挑战和知识点列表 / 字典 / 函数 / 递归 / 文件 / 装饰器。实际操作时不需要写代码用 Excel 就足够。整理出来的索引表结构推荐这样题号章节难度知识点代码状态备注1基础语法入门变量、print通过无需修改17循环进阶while、break通过边界条件需注意34函数挑战递归、列表推导语法错误题目本身有问题这个表的价值在于复习阶段。你不需要从头到尾再刷一遍直接筛选“知识点递归”或“难度挑战”就能精准定位。打标签阶段最重要的原则不要贪多。标签控制在 2~3 个维度就够了。我之前见过有人给每道题打了七八个标签最后维护成本比刷题成本还高这种过度设计反而是翻车的前兆。题库的价值在练不在存做完标签赶紧进入下一个环节。4.3 不值得做的题直接标记删除或合并有个我一开始很舍不得后来发现必须做的事删题。有些题明显是过时或错误的比如让你用xrangePython 2 专用或者让你用已经移除的os.system来做某种操作。这些题放进练习列表只会浪费半小时然后让人困惑“为什么我的代码报错”。常见的处理策略是标记为“已废弃”不再安排练习。把同一知识点的重复题合并掉。比如连续 10 道“冒泡排序变体”留 2~3 道做透就够了。对答案有争议的题比如“下面哪个写法更好”这类主观题如果你只是一个人刷题直接删掉因为没人讨论价值很低。在题库文档上做这些操作我没用自动化脚本而是用 Word 的批注功能直接标记。因为判断一道题要不要留本质是主观判断脚本帮不上忙。这个过程像在整理自己的工具箱——留下的每样东西都要用得上用不上的就果断扔留着只会增加每次翻找的成本。5. 自动化抽题与批量练习把题库变成每日训练场5.1 写一个随机抽题脚本按难度和知识点出题题库整理好了接下来让它发挥作用。最常见的使用方式是随机抽题。这里有个参数很关键怎么定义“随机”。如果完全随机可能会出现连续抽到同一个知识点的题如果按权重抽就能控制训练覆盖面。# 按知识点权重随机抽题 import random questions [ {id: 1, topic: list, difficulty: easy, content: ...}, {id: 2, topic: dict, difficulty: medium, content: ...}, {id: 3, topic: list, difficulty: hard, content: ...}, ] def pick_questions(q_list, count5, topic_weightsNone): if topic_weights is None: topic_weights {list: 2, dict: 1} # 按权重展开候选池 pool [] for q in q_list: weight topic_weights.get(q[topic], 1) pool.extend([q] * weight) return random.sample(pool, kmin(count, len(pool))) # 抽 3 道列表题1 道字典题通过权重体现 selected pick_questions(questions, count3, topic_weights{list: 2, dict: 1})逻辑说明pool.extend([q] * weight)是“按权重放大候选池”的经典做法。列表权重为 2那么列表题被抽中的概率就是权重 1 的字典题的两倍。random.sample做不放回抽样避免同一道题被重复抽到。这个脚本的参数不需要太多三个就够用——抽题数量count、知识点权重topic_weights、以及从哪些题里抽q_list。权重值不需要精确它是相对关系。如果连续抽出来的题太难或太简单调一下权重比例就行。换一个更精细的思路你现在真正需要的是能按“遗忘曲线”排题的脚本也就是根据你上次做错的情况把错题加权抽出来。这个怎么做在后一章讲。先跑通抽题脚本的意义在于你能在没有心理负担的时间里每天固定看到几道不一样的题形成刷题节奏。5.2 让代码自己跑用 subprocess 执行答案并抓取输出练习编程题有一个痛点是写完代码不知道对不对。如果题库里带答案比较好的使用方式是——你先自己写一版再用 subprocess 去跑这一版和答案版对比输出。这正是让题库“完整版”的价值发挥出来的地方。# 运行代码块并捕获输出 import subprocess import sys def run_code_snippet(code, timeout5): with open(temp_code.py, w, encodingutf-8) as f: f.write(code) try: result subprocess.run( [sys.executable, temp_code.py], capture_outputTrue, textTrue, encodingutf-8, timeouttimeout ) return { stdout: result.stdout, stderr: result.stderr, return_code: result.returncode, } except subprocess.TimeoutExpired: return {stdout: , stderr: 运行超时, return_code: -1} code for i in range(3): print(i) print(run_code_snippet(code))这里先写临时文件再执行的原因在于subprocess 需要接收一个可执行文件路径不能直接传字符串代码。sys.executable获取当前解释器路径保证用的是同一套 Python 环境。capture_outputTrue捕获标准输出和错误流textTrue让输出以字符串形式返回而不是字节。参数说明timeout5最好根据题目复杂度设置。递归或全排列类题目可能跑得慢可以调到 10而基础题 2 秒就够。超时返回-1用于标识“这道题可能有死循环”。这个功能最大的价值在于批量验证答案。你把题库里所有代码块跑一遍就能确认哪些答案是能跑的哪些自带 bug。不过需要注意的是题库里有少量题目会调用input()等待键盘输入如果直接跑会卡住直到超时。解决方法是先检测代码里有没有input(有就跳过或者传入预设输入。关于这个“input 陷阱”我在后面避坑还会再提。5.3 用 pytest 包装练习题把题目转成“可测试用例”练习到一定量之后你可能会想做一件事把某些经典题变成自动化测试用例以后每次改动代码都能回归验证。用 pytest 就能把题目包装成用例。# 把题库第 7 题包装成 pytest 用例 # 题目实现 add(a, b) 返回两数之和 def add(a, b): return a b def test_add(): assert add(1, 2) 3 assert add(0, 0) 0 assert add(-1, 5) 4逻辑说明test_add是 pytest 识别测试函数的固定前缀。写三个断言覆盖正数、零、负数场景执行pytest就能看到测试是否通过。这个思路从“刷题”变成了“测试驱动”工程味道更浓。参数说明断言数量不用多三道五个就能覆盖主要分支。重点测试边界比如空列表、单个元素、极大值。如果题目答案里自带测试用例优先复用如果没有自己补边界的成本不高。这节的目的是让你体会到整理题库最终不是为了“看完”而是为了“跑起来”。哪怕是同一道题用 pytest 包装之后它就从静态文字变成了一个可以重复执行、可以验证的分支逻辑。新手用这个方式能建立“代码是对是错”的判断标准熟手能把它接进自己的练习框架。6. 避坑指南处理 Python 题库的五个高频翻车现场6.1 现象UnicodeDecodeError: gbk codec cant decode byte 0x80原因文件实际是 UTF-8 编码但你用 GBK 打开。这种情况常见于从网上下载的 .doc 被转成 .txt或者文档里有特殊表情符号。解决按前面read_text_smart的方式做编码探测或者直接用编辑器如 VS Code打开后看右下角编码提示。稳妥做法是统一转成 UTF-8 无 BOM 格式再处理# 强制写入 UTF-8 无 BOM with open(output.py, w, encodingutf-8) as f: f.write(cleaned_code)6.2 现象代码能编译但运行报NameError: name xxx is not defined原因题目答案是一个片段依赖前文定义的函数或变量。题库文档为了篇幅会把上下文省略掉直接复制片段运行必然报错。解决遇到这种题不要硬跑。把缺失的变量定义补一个简单的默认值放在代码块开头。比如题目说“利用已有的 data 列表”你就在代码块前加一行data []。如果题目本身没有说明 data 是什么这一道题可以直接跳过多半题目质量不行。6.3 现象代码运行后卡住不动直到超时原因题目包含input()等待用户输入或者代码里有死循环。题库里有些题在while循环里漏了条件更新跑起来就是死循环。解决优先检测input(有的话给代码追加预设输入# 自动追加 input 模拟输入 code code.replace(input(), input(模拟输入))更稳的办法是运行前设置一个比较短的超时比如 3 秒。超时就把这道题标记为“需人工检查”不要让它一直挂住整个练习流程。6.4 现象全角空格导致若干行代码看起来对齐但一跑就报IndentationError原因中文输入法在代码缩进的位置误输空格尤其是复制粘贴的时候Word 自动把半角空格替换成全角空格。这行代码在文本层面多了一个不可见字符编辑器可能没显示出来。解决用正则把行首和行尾的全角空格全部清掉# 清洗行首行尾的全角空格 lines [re.sub(r^[\u3000]|[\u3000]$, , line) for line in lines]只消行首行尾是因为行中间的全角空格通常在字符串常量里清洗会影响输出结果。行首行尾属于格式问题必须清。6.5 现象题库里的答案是 Python 2 语法比如print hello原因文档太老里面是 Python 2 时代的代码。print作为语句而非函数在 Python 3 下直接SyntaxError。解决对这类题有两个选择。一是用 2to3 工具批量转换语法# 使用 2to3 将 Python 2 代码转为 Python 3 2to3 -w legacy_code.py二是直接把题目标记为“已过时”跳过不练。我建议后者优先——因为老题库里的 Python 2 题不仅语法过时思维方式也可能过时比如不强调异常处理、不强调上下文管理器练了反而会形成不好的习惯。7. 进阶玩法把题库接进每天的自动化练习流程里整个题库处理到最后最让人舒服的状态是每天打开终端跑一个命令今天该练的题就出现在屏幕上做完自动记录对错第二天按遗忘曲线安排复习。我给自己搭的这套流程核心是一个practice.py脚本配合一个简单的 JSON 文件存错题记录。脚本核心逻辑不复杂从题库里按权重抽题把题目打印到终端等你写完答案后手动输入y/n表示是否通过。通过的就标记“今天已完成”没通过的进入错题表下次抽题时权重提高 3 倍。# 每日练习调度脚本简化版 import json import random from datetime import date def load_progress(): try: with open(progress.json, encodingutf-8) as f: return json.load(f) except FileNotFoundError: return {wrong_questions: []} def save_progress(data): with open(progress.json, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse, indent2) def pick_daily(questions, wrong_ids, count3): # 错题权重放大 3 倍 pool [] for q in questions: weight 3 if q[id] in wrong_ids else 1 pool.extend([q] * weight) return random.sample(pool, kmin(count, len(pool))) progress load_progress() daily pick_daily(questions, progress[wrong_questions])这里值得注意的地方是ensure_asciiFalse。如果不加这个参数JSON 里的中文题面全会变成\uXXXX转义序列读起来完全没法看加上之后直接存原始中文可读性提升巨大。indent2则是让 JSON 文件按两空格缩进方便你打开看结构也方便 git 做差异对比。错题记录用 JSON 而不是数据库原因是练习场景数据量很小、结构简单JSON 文件用文本编辑器就能查看和修改。你在做错一道题之后把它加入错题列表不需要额外的“复习状态机”只要权重放大它自然会在未来几天的抽题里高频出现直到你连续答对几次后因为不再进入错题列表而自然“毕业”。这个手法的好处是零额外依赖又能把“反复做错题”这个目标不动声色地嵌在流程里。最后想给一个经验之谈一份题库文档的价值往往不在题量多少也不在答案是否完美而在于你能不能让它持续产生反馈。我见过有人整理完题库后雄心勃勃定了一堆计划最后因为流程太重、每天要打开三个工具才能开始刷题而放弃了。我的习惯是所有步骤能合并就合并最终只留一个命令、一个文件。如果你整理完题库能有一个类似“打开终端输入 python practice.py进入今日题目”的一键闭环这个题库就算是真正兑现了价值。希望帮到你。本文还有配套的精品资源点击获取