理解条件、循环、函数和对象的基本写法后,还需要进一步判断:分支是否覆盖边界,循环能否正确结束,函数调用是否共享数据,对象状态是否按预期变化。这些问题直接影响生成代码的正确性,也决定了修改后的程序能否继续可靠运行。
通过小规模推演、对照实例和完整任务,可以把执行规则与实际结果联系起来。先根据输入独立预测,再追踪状态变化,有助于定位错误,并理解不同程序组织方式的适用条件。
一、程序控制
1.1 分支顺序与边界覆盖
多分支结构按顺序判断条件,只执行最先成立的分支。条件可以存在包含关系,因此排列顺序会影响结果。分类之前还应检查数据是否符合输入约定,避免将无效数据归入正常类别。
边界测试应包含阈值本身及其两侧的数据。多个分段规则还需要分别检查,不能只用一个中间值代表全部情况。
# 后面的优秀判断就无法处理这条记录。1.2 累加循环的不变关系
检查循环时,除了观察最终结果,还可以寻找每轮判断时始终成立的关系。这样的关系称为循环不变式(Loop Invariant),能够帮助解释初始状态、更新步骤和结束后的结果。
对于连续整数求和,在每次判断是否继续时,总和应等于此前已经处理过的整数之和。证明这一关系,需要检查它在循环开始前成立,并且每轮更新后仍然成立;再结合终止条件推导最终结果。
循环不变式说明已经完成了什么;终止条件说明还需要处理什么。两者结合,才能判断循环是否恰好覆盖预定范围。
1.3 嵌套循环与输出规模
嵌套循环的执行次数取决于内外层范围。
内层范围固定时,可以按外层次数累加;内层范围随外层变化时,应分别计算每轮的工作量。
乘法表每一行的项目数随行号增加,总项数可以独立推导:
print("总项数:", item_count) # 45 ![]()
图 1-1:嵌套循环与内外层执行
相同的输出也可能采用不同的组织方式。比较两种实现时,应关注它们表达的操作层次,而不只比较代码长短。
# *****1.4 穷举范围与约束筛选
穷举(Exhaustive Search)在有限候选范围内逐一检查可能结果。有效的穷举需要先明确取值范围,再依据约束筛选。通过关系式减少独立变量,可以降低需要检查的组合数量。
百钱百鸡问题约定:公鸡每只 5 钱,母鸡每只 3 钱,小鸡每 3 只 1 钱,用 100 钱购买 100 只鸡。设公鸡、母鸡和小鸡的数量分别为 x、y、z,均为非负整数,则有:
利用总数约束消去小鸡数量,再将价格约束转换为整数等式:
![]()
图 1-2:百钱百鸡的约束与穷举过程
取值范围和筛选条件共同决定合法结果。修改题目约束后,应重新检查搜索范围与验收结果。
1.5 素数判断与平方根边界
素数是大于 1、只有 1 和自身两个正因子的整数。如果一个合数可以分解为两个正整数因子的乘积,其中至少一个因子不超过其平方根。因此,试除只需检查到平方根的整数部分。
1 $$">
检查范围必须包含平方根端点,完全平方数尤其适合发现边界遗漏。对于整数,可以使用整数平方根确定范围,避免浮点计算带来的取整问题。
![]()
图 1-3:素数试除与平方根边界
优化方法可以用更直接的实现交叉检查。在较小范围内统计全部正因子,虽然计算较多,却便于独立理解。
# 有限范围内一致能够帮助发现错误,不能替代对算法依据的解释。1.6 有限组合与分支核验
输入种类较少时,可以列出全部组合,检查分支是否覆盖完整。猜拳包含三种选择,双方共有九种合法组合,适合观察相等判断、成员判断和默认分支之间的关系。
数量检查可以发现部分遗漏,但仍需逐项确认胜负规则。对于嵌套循环,还应区分退出范围:提前结束内层循环后,外层通常仍会继续执行。
1.7 生成器表达式与按需求值
(Generator Expression)按需产生元素,适合将逐项计算的结果交给求和、遍历等操作使用。它可以避免立即保存全部结果,但也会保留尚未完成的计算过程。
按需求值还意味着部分计算在后续取值时才发生。需要固定当时的结果时,应明确是否立即收集数据。
print(results) # [86, 91]二、函数与程序组织
2.1 返回约定与空输入
函数接口应说明正常结果与特殊情况的返回方式。没有可计算的数据时,使用明确的缺失标记,可以保留“无结果”与“结果为零”的区别。
返回形式应保持稳定,使调用者能够按同一接口接收结果。显示文字和输出格式可以由调用者决定,计算函数则保持职责清楚。
2.2 参数收集与调用解包
星号(*)在函数定义与调用位置承担不同作用:定义时收集实参,调用时展开已有数据。阅读时应先确认位置,再判断数据如何与参数对应。
可变参数适合数量不固定的输入,但仍需要明确允许的数据类型和含义。接收形式灵活,并不意味着输入无需约束。
2.3 默认参数与共享状态
默认参数表达式在函数定义执行时求值。如果默认值是可变对象,省略参数的多次调用可能共同使用这个对象。
需要为每次调用建立独立容器时,可以使用缺失标记,在函数内部创建对象。显式传入已有容器时是否修改它,则属于另一项接口约定。
局部名称与对象隔离是不同问题。参数属于当前调用的局部名称,但它可以引用调用者仍在使用的对象。
2.4 函数式操作与结果消费
函数可以作为参数传递,使遍历过程与处理规则分别表达。 将函数应用于各元素, 根据判断结果保留元素;两者返回迭代器,结果随着取值被消耗。
![]()
图 2-1:函数作为参数与数据处理过程
函数作为参数不会自动消除副作用。仍应检查传入的函数是否修改共享对象、写入文件或改变其他状态。
2.5 全部条件与空输入
批量检查常需要判断是否每项都符合要求。 在遇到假值时停止检查;如果没有元素,则返回真。因此,“每项均符合条件”与“至少有一项数据”需要分别表达。
空输入应得到什么结果,由任务约定决定。求和、平均分、分类汇总等操作,对空输入可能采用不同处理方式。
2.6 迭代与递归的状态推演
迭代通过重复更新状态推进计算;递归通过同类调用求解子问题。递归需要可以直接求解的基本情形,并保证调用逐步接近它。
猴子吃桃问题约定:前九天每天早上吃掉现有桃子的一半,再多吃一个,第十天早上吃桃前剩一个。前一天与后一天的数量关系为:
# 若缺少基本情形,调用无法按预期结束。递归会增加函数调用层次,过深的调用可能达到解释器的递归限制。
只需保留上一步状态的连续计算通常适合迭代;树形结构等问题则可能适合递归表达。选择时应同时考虑可读性、终止条件和资源开销。
三、面向对象基础
3.1 独立实例与共享类属性
实例属性可以保存各实例独立的数据。类属性由类保存,多个实例可以访问同一个属性;当属性指向可变对象时,一次修改可能被多个实例观察到。
需要独立容器时,应在每次初始化过程中分别创建。
![]()
图 3-1:实例属性与共享类属性
是否共享应由任务决定。公共配置可以适合共享,每个对象的独立记录则通常应分别保存。
3.2 绑定方法与当前实例
访问普通实例方法时,会取得与当前实例关联的绑定方法(Bound Method)。调用它时,实例作为第一个参数自动传入。取得方法与执行方法是两个不同操作。
方法对象可以保留与实例的联系。再次调用时,读取的仍是实例当时的状态。
print(operation()) # 263,使用更新后的成绩。3.3 方法约束与属性访问
对象可以通过属性引用其他对象。当这些对象共同表示整体与部分的关系时,可以用组合组织数据,例如成绩册持有成绩列表。
方法能够集中检查输入,但只有通过这些方法进行的操作才会执行相应检查。外部代码直接修改可访问的内部容器时,可能绕过约束。
检查对象代码时,应同时阅读类提供的操作与外部访问方式。类定义中的检查无法自动保证所有使用路径都遵守同一规则。
3.4 输入复制与共享层次
初始化时复制输入容器,可以使实例拥有新的外层容器。但普通浅复制不会自动复制全部嵌套对象,应根据数据层次判断实际隔离范围。
预测对象变化时,应明确修改发生在哪一层:名称重新绑定、外层容器改变和内部对象改变,影响范围各不相同。
四、大模型代码的阅读与应用
4.1 任务约定与生成请求
完整实例可以将控制结构、函数接口和数据检查联系起来。练习使用程序内的虚构记录,先验证处理规则,再考虑后续的文件读取与保存。
可向大模型提出以下请求:
请使用 Python 编写一个登记成绩核验与汇总程序。
输入为四条字典记录,字段包括学号、姓名、数学、英语、物理和来源文件,已有字段的值均为字符串:
• 001,姓名“ 张三 ”,三科成绩为“85”“90”“88”,来源为“登记表01.docx”。
• 002,姓名“李四”,三科成绩为“92”“85”“79”,来源为“登记表02.docx”。
• 003,姓名“王五”,三科成绩为“120”“72”“85”,来源为“登记表03.docx”。
• 004,姓名为空,三科成绩为“95”“98”“92”,来源为“登记表04.docx”。
学号和姓名去掉两端空白,均不能为空,学号保持文本。成绩去掉两端空白后,应为 1 至 3 位十进制数字文本,转换结果必须在 0 至 100 之间。
有效记录计算总分和均分,均分显示一位小数。问题记录保留输入序号、学号、来源文件和首个问题原因,并继续处理后续记录。分别保存两类结果,核对数量是否覆盖全部输入。
请用条件、循环和函数组织程序,在注释中说明关键约定。保留原始记录,不读取或写入实际文件,暂不检查重复学号。先说明处理步骤,再生成完整代码。
独立验收结果应在运行前确定:前两条有效,总分分别为 263 和 256,均分分别显示为 87.7 和 85.3;第三条成绩超出范围,第四条姓名为空。因此,应得到两条有效记录和两条问题记录。
4.2 完整实现与接口衔接
单条处理负责检查和整理,批量处理负责遍历、分类与计算。明确区分这两层职责,可以分别核查局部规则和整体完整性。
这一实现适用于约定的字符串字段。外部数据若可能包含其他类型,还需要扩展输入检查;来源文件缺失是否应拒绝,也应由任务另行约定。
4.3 执行路径与退出范围
不同退出语句影响的范围不同。结束当前函数调用后,调用者仍可继续执行;跳过当前循环的一轮后,后续输入仍可处理;结束循环则可能留下尚未检查的数据。
数量核对用于发现部分遗漏,内容核对则用于确认规则正确。两类检查需要配合,不能用其中一项代替另一项。
4.4 单项修改与回归检查
修改输入或规则前,应先预测哪些结果会变化、哪些结果应保持不变。这样可以检查相关功能,也可以发现修改意外影响了其他部分。
使用原始材料再次运行,可以确认基准结果仍然一致。当程序实现发生修改后,重新运行原有测试、检查既有功能是否受到影响,称为回归测试(Regression Testing)。新增要求应另行核验,并与回归测试配合进行。
4.5 格式、范围与边界测试
输入检查可以分为不同阶段:文本是否符合格式、转换是否得到所需类型、数值是否落在允许范围。测试材料应分别触发这些条件,便于判断问题发生在哪里。
若任务只允许半角数字,应同步修改提示词、检查条件和预期结果。输入规则必须由任务明确决定,不能仅根据某个转换函数是否接受来判断。
4.6 新增字段与可变结果
新增统计结果时,需要明确计算范围及结果所属对象。每条记录的可变结果应分别建立,避免多个记录共享同一个列表。
print(failed_subjects) # ['数学'],60 分不属于不及格。4.7 接口说明与后续扩展
关键函数的说明应包含可接受输入、正常返回、无效输入的处理方式,以及是否修改传入对象。完整流程还应保留来源与问题原因,使结果可以追溯。
进一步接入 JSON、Word 或 Excel 文件时,可以保留已核验的数据检查与计算函数,在外层补充读取、格式验证和保存。文件读取成功之后,仍需检查所得对象是否符合原有接口约定;新增的异常情况也需要独立测试。
简单的批量处理可以使用函数与容器清楚表达。需要持续管理多个实例状态时,再引入类,并检查对象之间的数据共享和修改范围。
小结
循环不变式、有限穷举和边界样例帮助检查控制流程;参数解包、共享默认值与递归说明函数调用机制;实例属性、绑定方法和组合揭示对象状态。完整案例进一步连接输入约定、分类处理、修改验证与回归检查。
“点赞有美意,赞赏是鼓励”
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.