
简介面向Python初学者和备考者整理的练习题PDF系统梳理了Python综合练习题目包含填空、选择、程序改错、程序填空与阅读程序等题型覆盖基本概念、语法、数据类型、控制结构、函数、模块、异常处理、文件输入输出等核心知识点并附有答案便于自测与查漏补缺。资源包共1个文件类型为PDF大小1.07MB便携易用适合打印或电子阅读。该资料已有706人学习下载可用于课程考试、等级考试或日常编程巩固。内容针对字符串切片、字典操作、内存管理等易混淆环节设计了典型练习能帮助读者快速定位薄弱点提升应试与实操能力。1. 一份25页的Python试卷到底在考什么如果你在搜索框里敲下“Python考试试卷试题整理”大概率是两类人一类是刚学完Python基础、想用综合练习题检验自己的初学者另一类是要给学员或团队出题的讲师、技术组长。一份25页的附答案PDF放在电子书堆里不算厚但覆盖的知识密度往往超过很多300页的教程——选择题测语法细节填空题测函数返回值编程题测逻辑与调试能力。先别把它当普通文档下载完就扔进收藏夹真正有用的做法是把这份试卷当成一份“考点地图”自己动手拆解每一道题背后的知识点再用脚本把题目整理成可复用的题库。这篇博客就顺着这条路走一遍先给题目分层再教你用Python写一个自动组卷脚本最后把刷题变成可验证、可追踪的过程。适合刚学完语法但不知道练什么的人也适合要维护内部题库的开发者。2. 从练习题到考点地图Python必考的知识点分层拿到一份综合练习题第一件事不是对着答案做而是把题目按知识点分类。我一般会按四层拆基础语法与内置函数、函数与作用域、面向对象与异常、文件与模块。这样拆完复习时就能针对薄弱项定点突破。2.1 基础语法与内置函数最容易失分的选择题地带选择题的干扰项很喜欢考“看似相似但结果不同”的写法。比如range(1, 10, 2)、[1, 2, 3] * 2、a 1这类题考的是对对象模型和运算符的理解不是背语法表。整理题目时我会把每道选择题的选项和正确答案放在一起然后标注它考核的具体函数或运算符。考点常见考察方式典型坑可变对象与不可变对象函数参数传递列表作为默认参数被修改切片与步长字符串和列表操作s[::-1]反转内置函数map/filter/sorted的返回值Python 3 中map返回迭代器逻辑运算and/or短路求值返回值是操作数而非布尔值做这类题的技巧是在终端里快速验证一遍不要只凭记忆。比如sorted([1, -2, 3], keyabs)的结果是什么写个.py文件跑一下比背答案有效得多。整理时也可以给每个知识点附一个“最小验证代码”这样后续复看时能直接看到运行结果。2.2 函数、作用域与装饰器闭包是分水岭函数部分是综合练习题的“分水岭”闭包和装饰器几乎是必考题。常见的题目是写出下面代码的输出然后解释为什么。例如def outer(x): def inner(): return x 1 return inner f outer(10) print(f())答案当然是11但考点不止于此。考核点在于inner捕获了xouter返回后x依然存活这就是闭包的定义。整理这类题时我习惯把“输出结果”和“内存行为”分开记录——前者是答案后者是原理。装饰器题更容易变形。比如用functools.wraps保留原函数名或者带参数的装饰器。答这类题的关键是理解“函数也是对象”装饰器本质是接收函数并返回新函数的可调用对象。2.3 面向对象与异常设计题的标准套路面向对象的题目往往不是考语法而是考设计。比如“设计一个银行账户类支持存款、取款、查询余额并处理透支异常”。这种题要写完整的类定义还要注意私有属性、类属性与实例属性的区别。class Account: bank Python Bank # 类属性 def __init__(self, owner, balance0): self._owner owner # 约定私有 self._balance balance # 私有余额 def deposit(self, amount): if amount 0: raise ValueError(deposit amount must be positive) self._balance amount def withdraw(self, amount): if amount self._balance: raise InsufficientFundsError(balance not enough) self._balance - amount property def balance(self): return self._balance上面的代码值得注意的点有两个一是用_前缀表示私有属性而不是__因为后者会触发名称重整容易让初学者困惑二是自定义异常InsufficientFundsError要继承Exception这样才能被except捕获。异常部分常考的还有try/except/else/finally的执行顺序——else在无异常时执行finally无条件执行。2.4 文件、模块与第三方库实操题的出题方向试卷最后的编程题通常会让考生自己实现一个带文件读写的小工具。比如“读取一个CSV文件统计每列的平均值将结果写入JSON文件”。这考察的是open()的上下文管理器、csv模块、json模块以及路径处理。import csv import json rows [] with open(data.csv, r, encodingutf-8) as f: reader csv.DictReader(f) for row in reader: rows.append(row) if rows: keys list(rows[0].keys()) result {} for key in keys: values [float(r[key]) for r in rows if r[key]] result[key] sum(values) / len(values) if values else None with open(result.json, w, encodingutf-8) as f: json.dump(result, f, ensure_asciiFalse, indent2)这段代码的注意点是DictReader的行是OrderedDict用float(r[key])转换时要处理空值json.dump设置ensure_asciiFalse能让中文正常显示。这个片段本身就是一道很好的综合题把文件、类型转换、异常处理全串起来了。3. 用Python脚本自动生成“附答案”试卷题库整理的正确姿势当你手里有上百道练习题手动调整排版和答案顺序太痛苦。我一般会维护一个题库文件然后用脚本自动抽题、组卷、生成PDF。这样既能保证每次练习的题目不同也能把答案解析放在一起省去翻页的麻烦。3.1 题库数据结构的选型JSON 还是 CSV题库的存储方式决定了解析代码的复杂度。如果每道题包含题干、选项、答案、知识点标签CSV 会因为逗号和换行炸开所以优先用 JSON。每道题存成字典整份题库是列表。[ { id: 1, topic: 函数, question: 下列哪个语句能正确生成一个生成器, options: [(x for x in range(10)), [x for x in range(10)], {x for x in range(10)}, range(10)], answer: A, analysis: 生成器表达式使用圆括号 }, { id: 2, topic: 内置函数, question: abs(-3.14) 的结果是, options: [-3, 3, 3.14, -3.14], answer: C, analysis: abs 返回绝对值 } ]JSON 的好处是天然支持嵌套答案和解析可以放在同一结构里。字段统一用英文驼峰或下划线避免中文键在切换环境时编码出问题。3.2 随机抽题与组卷算法一份模拟卷要兼顾难度和知识点分布不能纯随机。我常用的策略是按知识点分组再从每组中随机抽取固定数量题目最后把选定题目打乱顺序。这样既保证覆盖面又避免相邻题目考查同一个点。import json import random def load_questions(path): with open(path, r, encodingutf-8) as f: return json.load(f) def build_exam(questions, per_topic3, shuffleTrue): by_topic {} for q in questions: by_topic.setdefault(q[topic], []).append(q) selected [] for topic, qs in by_topic.items(): selected.extend(random.sample(qs, min(per_topic, len(qs)))) if shuffle: random.shuffle(selected) return selected参数说明per_topic控制每个知识点抽几道设为 0 则跳过该知识点shuffle为真时会打乱最终题目顺序模拟真实考试试卷的混合出题。如果题库里某个知识点题目不够random.sample会抛异常所以用min()限制抽取数量。这样的组卷脚本足够支撑一份25页左右的PDF练习册。3.3 生成带答案的PDFreportlab 与 markdown 的取舍生成PDF有两条路用reportlab直接绘制或者先把内容转成 markdown 再用工具转PDF。reportlab的优点是最终排版可控适合中英文混排和代码块缺点是API较底层写起来繁琐。我一般只生成题目、选项和答案表格不处理复杂公式所以用reportlab就很顺手。from reportlab.lib.pagesizes import A4 from reportlab.pdfgen import canvas from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfbase import pdfmetrics pdfmetrics.registerFont(TTFont(SimSun, SimSun.ttf)) # 中文字体 def save_pdf(selected, output_path): c canvas.Canvas(output_path, pagesizeA4) width, height A4 y height - 40 for i, q in enumerate(selected, 1): if y 100: c.showPage() y height - 40 c.setFont(SimSun, 10) text f{i}. ({q[topic]}) {q[question]} y draw_text(c, text, width - 80, y) for j, opt in enumerate(q[options]): y - 18 c.drawString(60, y, f{ABCD[j]}. {opt}) y - 18 c.setFont(SimSun, 9) c.setFillColorRGB(0.4, 0.4, 0.4) c.drawString(60, y, f答案: {q[answer]} 解析: {q[analysis][:30]}...) y - 30 if y 80: c.showPage() y height - 40 c.save() def draw_text(c, text, max_width, y): # 按宽度截断避免超界 while c.stringWidth(text) max_width: line text[:int(len(text)/2)] c.drawString(50, y, line) y - 15 text text[int(len(text)/2):] c.drawString(50, y, text) return y - 15 save_pdf(exam_questions, exam.pdf)这里的draw_text是简陋的按半宽截断实现实际工作中建议引入textwrap按字符宽度处理。中文PDF一定要注册中文字体否则会显示乱码或方块。canvas对象写满一页后调用showPage()自动翻页这是生成多页PDF的关键。3.4 参数说明与运行效果运行组卷脚本时我通常会加两个参数一个是--seed传入随机种子保证同一份试卷可以复现另一个是--answer开关控制生成的PDF是否附带答案。考试版和练习版用同一份题库只是输出不同。python build_exam.py --per-topic 5 --seed 42 --output exam.pdf python build_exam.py --per-topic 5 --answer --output exam_with_answer.pdf--seed很重要。随机组卷如果不指定种子每次生成结果都不同不方便下次讲解同一道题。设置同一个种子random会生成相同的随机序列同时也便于回归测试——题库改动后对比新旧试卷题目是否仍符合预期。4. 综合练习题的答案解析5个必考易错点拆解整理“附答案”的试卷本质上是在整理易错点。下面这5个点几乎是每套综合练习题的常客答案背下来不难但能讲清楚为什么才算掌握。4.1 可变对象默认参数def f(lst[]) 的陷阱def add_item(item, lst[]): lst.append(item) return lst print(add_item(1)) # [1] print(add_item(2)) # [1, 2] 而不是 [2]默认参数在函数定义时被求值一次之后所有调用共享同一个列表对象。所以每次调用add_item修改的都是同一个默认列表。把它改成lstNone函数体内再判断def add_item(item, lstNone): if lst is None: lst [] lst.append(item) return lst这是标准解法关键词是“可变对象默认参数”。题目里经常把[]换成{}或set()原理一致。4.2 作用域链与nonlocal闭包计数器的正确写法def counter(): count 0 def inc(): count 1 # UnboundLocalError return count return inccount 1在inc内部会创建一个新的局部变量因为赋值操作让解释器把它视为局部变量。解法是在inc内声明nonlocal count。考题常问“输出是什么”或“如何修复”回答时要说明nonlocal的作用是让内层函数能修改外层函数的局部变量。4.3 列表解析与生成器内存与效率的平衡一个经典题是计算[i * i for i in range(10000)]和(i * i for i in range(10000))的区别。前者生成完整的列表占用内存后者生成生成器对象逐个求值。如果题目让计算sum(i * i for i in range(10000))用生成器表达式不会创建大列表这是更优写法。考场上经常混淆的就是圆括号和方括号的差异。4.4 浅拷贝与深拷贝copy模块的边界import copy a [[1, 2], [3, 4]] b a[:] # 浅拷贝内层列表仍是同一对象 b[0][0] 99 print(a) # [[99, 2], [3, 4]]a[:]拷贝了外层列表但没有拷贝内层列表。只有使用copy.deepcopy才会递归复制所有嵌套结构。考题里如果出现b[0] is a[0]答案就是True。整理这类题时我会画一个简单的引用图把可变对象和不可变对象的关系标出来。4.5 异常链与自定义异常print还是raisedef divide(a, b): if b 0: raise ZeroDivisionError(division by zero) return a / b try: divide(1, 0) except ZeroDivisionError as e: print(错误:, e) raise # 继续抛出保留原始堆栈raise不带参数会把当前异常重新抛出保留堆栈信息。如果写raise e虽然也能抛但会丢失原始异常上下文。Python 3 中的raise ... from e还能显式添加异常链。题目常考的是捕获异常后是打印还是重新抛出答案取决于调用方是否需要知道错误。如果只是提示用户print即可如果是库代码必须raise。5. 刷题效率翻倍把这25页变成自动化的错题本把PDF里的题目变成可执行的代码是比反复翻阅答案更高效的复习方式。我通常会将每道能运行的题写成一个独立的.py然后用pytest断言答案再结合间隔重复策略安排复习时间。5.1 用pytest给每道题写测试断言比如一道题是“编写函数返回列表去重后的元素个数”可以用一个测试文件锁住它# test_exercise.py def count_unique(lst): return len(set(lst)) def test_count_unique(): assert count_unique([1, 2, 2, 3, 3, 3]) 3 assert count_unique([]) 0 assert count_unique([a, a, b]) 2运行pytest -v test_exercise.py每个断言都通过才算真正把这道题做对了。比对着答案看“哦应该是3”要强得多。即使试卷里的题目没有要求写函数你也可以自己把答案改写成一个可测试的函数顺便练习封装能力。5.2 错题重练的间隔重复策略我会为错题在题库里打一个wrong_count字段每次做错就加一正确一次减一。组卷脚本优先抽取wrong_count高的题目并且让这些题间隔两次练习后再出现类似Anki的间隔重复。def prioritize(questions): return sorted(questions, keylambda q: -q.get(wrong_count, 0)) selected prioritize(qs)[:10]这样每一次练习都是针对薄弱点而不是从头到尾泛泛刷。同时每道错题补一句“为什么错”下次再看到时能快速回忆起失误原因。25页的PDF只是一个起点把它的内容拆解成结构化题库、生成可复现的试卷、用pytest验证答案你得到的是一套可以持续迭代的个人刷题系统。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。