
简介这份文档是刘卫国《Python语言程序设计》配套实验指导的部分参考答案面向正在学习Python基础课程、需要上机练习与对照自查的高校学生及自学者可帮助解决实验题卡壳、结果对不上等问题。压缩包内共1个doc文件约145KB按实验章节组织涵盖Python语言基础、顺序结构、选择结构、循环结构、字符串与正则表达式、列表与元组、字典与集合等模块逐题给出补充代码与运行结果。内容涉及math库计算π的平方、input与eval配合格式化输出出生日期、整数与小数部分分离、if-elif条件判断、while循环与嵌套循环求阶乘和、100至200间素数输出、字符串切片复制、元音首字母筛选、金字塔图案打印、列表频次统计及元组不可变导致的append报错修正等典型考点并附有浮点数比较误差的分析与修改思路。目前已有6689人学习适合按实验进度逐节对照练习、理解易错点并巩固语法基础。1. 一份实验答案的实战用法从填空到上机验证很多人拿到实验指导答案第一反应是对着填空位置抄一遍运行通过就关掉。但这份 Python 语言程序设计实验指导答案的价值恰恰不在“抄”而在于它把 15 个实验里最容易翻车的语法点、边界条件和运行结果都摊开了。它覆盖从 math 库运算、顺序结构、选择结构、循环结构到字符串与正则、列表与元组、字典与集合、函数、面向对象、文件操作、异常处理、tkinter 图形绘制和 GUI 设计的完整链路适合刚学完语法想上机验证的新手也适合带实验课的从业者拿来当排错参照。下面按“能跑起来、能改对、能避开坑”的顺序拆。2. 基础语法实验填空背后的类型与格式化逻辑2.1 math 库运算与浮点输出实验 1 第 6 题要求计算并输出 π²填空处是math.pi*math.pi。看起来简单但这里有个新手常忽略的点math.pi是浮点常量平方后仍是浮点直接print会输出一长串小数。如果实验要求保留固定位数就得自己套format。我一般会先跑一遍看原始输出再决定要不要格式化。import math p math.pi * math.pi # 填空①math.pi*math.pi print(p) # 原始浮点输出 print({:.4f}.format(p)) # 需要固定小数位时再格式化逻辑说明math.pi是 math 模块提供的圆周率常量平方运算不改变类型。参数上唯一能调的是输出格式{:.4f}表示保留 4 位小数按实验报告要求改数字即可。注意不要写成math.pi**2之外的花样填空只认这一种写法。2.2 顺序结构里的输入解析与补零格式实验 2 第 3 题用eval(input())一次性接收1992,12,5这样的输入再解包给y,m,d。这里的关键是eval会把输入当表达式求值逗号分隔自然变成元组。格式化部分{1:02d}和{2:02d}负责月份、日期补零这是实验报告里最常被扣分的地方——不补零就输出“12 月 5 日”和题目要求的“12 月 05 日”对不上。y, m, d eval(input()) # 输入形如 1992,12,5 print(我的出生日期是{0}年{1:02d}月{2:02d}日.format(y, m, d))参数说明{0}对应第一个参数 y{1:02d}中02表示宽度 2、左侧补零d表示十进制整数。第 4 题分离整数和小数部分同理int(x)取整、x-k取小数再用{0:f}{1:d}{2:f}拼回去。这里要留意eval的安全边界它只适合实验环境里自己敲的纯数字输入真实项目里换成map(int, input().split(,))更稳妥。2.3 选择结构浮点比较与整除判断实验 3 第 2 题是整份答案里最值得反复看的一题x2.1、y2.0判断x-y0.1却输出Not Equal。原因是二进制浮点无法精确表示 0.12.1-2.0实际得到0.10000000000000009。答案给的修法是round后再比这是常见做法。x 2.1 y 2.0 if round(x - y, 10) round(0.1, 10): print(Equal) else: print(Not Equal)逻辑说明round(x-y, 10)把差值截到 10 位小数消掉尾数误差。参数 10 不是固定值按精度需求调一般 8 到 12 之间够用。第 3 题判断能否被 3 或 7 整除填空是m%30 or m%70注意or不能写成||这是从 C 语言转过来的同学的高频翻车点。3. 数据结构与函数实验循环、容器与递归的边界3.1 循环结构里的 break 与嵌套阶乘实验 4 第 1 题的while i1是个反直觉写法i1恒为真循环靠内部break退出。答案输出135因为 i 从 1 开始每次加 2到 5 时满足i4打印并 break。第 2 题嵌套循环算阶乘和外层 j 从 1 到 3内层range(2, 2*(j1))控制乘到哪个数最终sum5167。这类题不要背结果把循环变量打印出来跑一遍最稳。sum_ j 1 while j 3: f 1 for i in range(2, 2 * (j 1)): f * i sum_ f j 1 print(sum, sum_)逻辑说明内层range(2, 2*(j1))的终点随 j 变化j1 时乘到 3j2 时乘到 5j3 时乘到 7。参数上唯一要盯的是 range 的右端点不包含所以写2*(j1)而不是2*j1。第 3 题素数筛选用math.sqrt缩范围if ik1判断没被整除这个写法比标志位简洁但要注意k2的边界。3.2 列表、元组与字典的不可变陷阱实验 7 第 2 题是经典错误p()建了元组循环里却p.append(x)直接抛AttributeError: tuple object has no attribute append。元组不可变要收集数据得用列表最后再tuple(p)转换。答案的修法就是这个思路。p [] for i in range(10): x int(input()) p.append(x) p tuple(p) print(p)逻辑说明列表append是原地修改元组没有这个方法。参数上没有可调的关键是理解“可变 vs 不可变”的选型需要动态增删就用 list需要固定结构、能当字典键就用 tuple。实验 8 第 2 题把元组当字典键numbers[(1,2,3)]1正是利用了元组可哈希的特性这一点和上面的陷阱是一体两面。3.3 函数与递归最大公约数与斐波那契实验 9 第 3 题求最大公约数填空是return n和gcd(n, m%n)标准欧几里得递归。第 2 题斐波那契递归foo(list, num)输出前 10 项[0,1,1,2,3,5,8,13,21,34]注意它用list[-1]list[-2]累加递归终止条件分num1和num2两支。def gcd(m, n): if m n: m, n n, m if m % n 0: return n # 填空① else: return gcd(n, m % n) # 填空② print(gcd(84, 342))逻辑说明先保证 m≥n余数为 0 时 n 就是最大公约数否则递归缩小。参数上m%n是核心别写成n%m。递归深度对这两个实验都很浅不用担心栈溢出但真实项目里大数斐波那契要换迭代或记忆化这是答案没展开、但从业者该知道的边界。4. 面向对象、文件与异常类继承、读写模式与异常链4.1 多继承的方法解析顺序实验 10 第 1 题GC(C1,C2)同时继承两条链gc.foo()输出called P1-foogc.bar()输出called C2-bar()。这是 Python 多继承的 MRO方法解析顺序在起作用foo 在 C1、C2 里都没重写沿继承链找到 P1bar 在 C2 里重写了优先于 P2。答案只给结果但理解 MRO 才能改对。class P1: def foo(self): print(called P1-foo) class P2: def foo(self): print(called P2-foo) def bar(self): print(called P2-bar) class C1(P1, P2): pass class C2(P1, P2): def bar(self): print(called C2-bar()) class GC(C1, C2): pass gc GC() gc.foo() gc.bar()逻辑说明GC(C1,C2)的查找顺序大致是 GC→C1→C2→P1→P2foo 最先在 P1 命中bar 最先在 C2 命中。参数上没有可调的选型上要记住多继承越深MRO 越难预测真实项目里优先用组合或单继承加接口。4.2 文件读写模式与 seek 复位实验 11 第 2 题用open(file.txt,w)写完后必须fo.seek(0)才能读回否则读指针在末尾read()返回空串。这是文件操作最典型的坑答案里seek(0)就是后悔药。第 3 题复制文件并转大写填空是w和f2.write。s 0 fo open(file.txt, w) for i in range(1, 10): fo.write(str(i)) fo.seek(0) # 关键读写指针复位 ls fo.read() fo.close() for x in ls: s int(x) if int(x) % 2 else 0 print(输出:{:d}.format(s))逻辑说明w是可读写模式但写入后指针停在末尾seek(0)把它拉回开头。参数上seek的偏移量按字节算文本模式下一般只用 0。第 3 题open(sample_copy.txt,w)的w会清空目标文件如果目标已存在且要追加得换a这是答案没强调但实际会踩的点。4.3 异常处理捕获顺序与自定义异常实验 12 第 3 题嵌套 try内层sa抛 TypeError 被内层except接住打印AAAAA随后s[0]4抛 TypeError 被外层接住打印BBBBB。第 5 题自定义DivisionExceptionraise后在except里再算x/y。这里要注意异常捕获是从内到外、从上到下匹配的。class DivisionException(Exception): def __init__(self, x, y): self.x x self.y y def main(): try: x, y 1, 2 if x % y 0: print(x / y) raise DivisionException(x, y) except DivisionException: print(DivisionExcetion:, x / y) main()逻辑说明自定义异常继承Exceptionraise后由同名except捕获。参数上x%y0是触发条件改成x%y0就不抛了。真实项目里自定义异常要带足够上下文别只存两个数否则排错时等于黑匣子。5. tkinter 与综合实验画布坐标、事件绑定与数值求解5.1 Canvas 绘图与彩条循环实验 13 第 2 题在矩形里画 10 条红色彩条填空是wTk()、c.pack()、c.create_rectangle。核心是x0从 35 开始每条宽 15、间隔 30循环 10 次。坐标系统以左上角为原点create_rectangle(x0,35,x015,225,...)的四个参数是左上和右下。from tkinter import * w Tk() c Canvas(w, bgwhite) c.pack() c.create_rectangle(30, 30, 325, 230, width5) x0 35 for i in range(10): c.create_rectangle(x0, 35, x0 15, 225, fillred, outlinered) x0 30 w.mainloop()逻辑说明x0 30控制彩条间距x015是彩条右边界两者差 15 就是条宽。参数上fill和outline都设红色才不留边框缝。注意mainloop()必须放最后否则窗口一闪而过。5.2 猜数字游戏的事件绑定与二分范围实验 15 第 3 题是综合 GUI用random.randint(1,1000)出题btnGuess绑定Button-1和回车每次猜完更新nmin/nmax标签本质是二分检索。答案里lbl_qv封装了标签更新numGuess按次数给评语。from tkinter import * import random number random.randint(1, 1000) running, num, nmax, nmin True, 0, 1000, 1 def btnGuess(event): global nmax, nmin, num, running if running: val1 int(ent.get()) if val1 number: lbl_qv(恭喜答对了) num 1 running False elif val1 number: if val1 nmin: nmin val1 num 1 lbl_min.config(textnmin) lbl_qv(猜小了请重新输入) else: if val1 nmax: nmax val1 num 1 lbl_max.config(textnmax) lbl_qv(猜大了请重新输入) else: lbl_qv(已经答对了)逻辑说明nmin/nmax维护当前可猜区间每次猜错只在新值更靠近答案时更新避免区间回退。参数上num15是评语阈值可按需改。事件绑定用bind(Button-1, btnGuess)而不是command因为要传 event 参数这是 tkinter 里容易混的点。5.3 NumPy 解线性方程组实验 15 第 4 题用 NumPy 的linalg.inv和dot解四元线性方程组输入 m1、m2、θ输出 a1、a2、N1、N2。答案给的xsol先构造 4×4 系数矩阵 A 和向量 B再dot(linalg.inv(A), B)。这里 θ 要转弧度t*pi/180不能漏。from math import * from numpy import * def xsol(m, n, t): A [[m*cos(t*pi/180), -m, -sin(t*pi/180), 0], [m*sin(t*pi/180), 0, cos(t*pi/180), 0], [0, n, -sin(t*pi/180), 0], [0, 0, -cos(t*pi/180), 1]] B [0, 9.8*m, 0, 9.8*n] C dot(linalg.inv(A), B) return C m1, m2, theta eval(input(m1,m2,theta)) print(xsol(m1, m2, theta))逻辑说明linalg.inv(A)求逆dot做矩阵乘向量返回四个未知数。参数上 g 取 9.8θ 以角度输入、内部转弧度。注意矩阵 A 必须可逆θ 取 0 或 90 的整数倍时可能奇异实际跑之前先看linalg.det(A)是否接近 0。6. 把答案变成自己的验证习惯与三个复查动作这份答案最容易被误用的地方是把它当成“标准输出对照表”。我踩过的坑是实验 4 第 1 题直接背了135换个数就懵实验 12 第 3 题以为内层异常会被外层接住结果捕获顺序记反。后来我固定了三个复查动作每个实验跑完都走一遍。第一个动作是打印中间变量。循环和递归类实验别只看最终 print把循环变量、递归参数在关键节点打出来和答案对不上时一眼能定位是边界还是初始值的问题。第二个动作是改一个参数再跑。比如实验 2 的{1:02d}改成{1:d}看输出怎么变实验 9 的gcd(84,342)换成互质数看返回 1改完还能跑通才算真懂。第三个动作是查异常类型。实验 12 那组题把每个except去掉跑一遍看 Python 报什么异常、在哪一行比背结果有用得多。下面这张表是我自己整理的高频翻车点对照跑实验时对着扫一眼能省不少时间实验现象根因处理实验 3 浮点比较输出 Not Equal二进制浮点尾数误差round 到 8~12 位再比实验 7 元组 appendAttributeError元组不可变先用 list 收集再 tuple实验 11 读回为空read() 返回空串写后指针在末尾seek(0) 复位实验 12 嵌套异常打印了外层信息捕获顺序从内到外确认内层 except 类型匹配实验 15 矩阵奇异求逆报错或结果异常θ 使矩阵不可逆先查 det(A) 是否接近 0还有一个习惯值得说答案里的eval(input())在实验环境没问题但凡是涉及真实数据录入我都会换成显式解析因为eval会把输入当代码执行这是血泪经验换来的边界意识。另外 tkinter 实验别在无图形界面的环境里跑Tk()会直接报错这不是代码问题是运行环境问题先确认有显示再排查逻辑。从那以后我每次拿实验答案上机都强制走一遍“打印中间量、改一个参数、去掉一个 except”这三步跑通了才敢说这题过了。希望帮到你。本文还有配套的精品资源点击获取