- Contract 约定: inputs and promised results
- State 状态: changes retained after a call
- Evidence 证据: examples, boundaries and invariants
全部讲稿
展开
- 第 1 页 · Objects and Encapsulation 对象与封装
上一讲通过规格、接口、边界和副作用检查程序。本讲继续研究数据与操作怎样组织,先观察一个对象怎样初始化和调用方法,再分析共享数据和有效状态。
类是组织方式,不会自动保证实现正确。讲义保留完整程序,课堂按主线理解调用与数据关系;三角形、向量等较长例子放在参考区。
- 第 2 页 · Part IV · Abstraction and Organization
课程进入抽象与组织部分。L09 学习类、实例、初始化、方法绑定和状态规则;L10 再讨论继承、运算协议与模块。
先说明本讲边界,不提前使用后续语法。已经学过的函数仍是有效工具,今天增加一种组织多个记录和相关操作的方法。
- 第 3 页 · Data, Interfaces and Verification 数据与接口
回顾 L08 最后一页的数据与操作。一个接口不仅有返回值,也可能修改原对象、打印消息或拒绝某些输入。
本讲继续分别观察这些结果。使用类以后,原有的规格、边界和副作用检查仍然适用,不能因为程序看起来更有结构就跳过验证。
- 第 4 页 · Two Position Records 两条位置记录
先不看代码。两个点各有坐标,移动 A 后要保留新的位置,B 的坐标通常不应改变;距离查询需要读取两个点。
请学生说出哪些数据需要长期保存、哪些操作修改它们、哪些操作只查询。现在只描述任务,不提前要求理解 class 或 self。
- 第 5 页 · Quiz 1 · Record Updates
开场题只使用已经教过的字典、函数调用、赋值和 print。预测原字典的 x 和函数返回值,不需要类的知识。
本题提交一次,先不揭晓,第 26 页用函数与方法的对应行为回顾原分布,不重新提交。
- 第 6 页 · Lecture Structure
顺序从创建记录、调用操作推进到验证状态,再比较哪些数据或操作属于类级共享。前一段得到的规则支持后一段的问题。
不重复独立 AI 政策页,实验中保留实际使用声明。下面的例子先从已有字典与函数开始。
- 第 7 页 · I · Objects and Initialization
函数已经可以接受字典记录,并隔离局部参数。引入类的目的不是否定这些写法,而是为一类实例组织共同接口和各自状态。
先看类、属性和初始化,再区分别名与新实例。没有初始化的属性与非法数值是两个不同问题。
- 第 8 页 · Records and Operations 记录与操作
字典版本把两个坐标放在同一个记录中,distance 接收两份记录,实际计算得到 5.0。讲义中提供完整独立程序。
类可以使相关操作的接口更集中,但不能因此声称字典版本不正确、方法调用必然更自然或类更快。后面始终保留这种选择依据。
- 第 9 页 · Existing Types and Methods 既有类型与方法
学生已经使用整数、字符串和列表对象。type 返回运行时类型,字符串 count 是通过对象访问的方法。
列表 reverse 返回 None,但列表实际变成 [2, 1, 3]。这仍是返回值与副作用的区分,不把 None 理解为没有执行。
- 第 10 页 · Classes and Instances 类与实例
class 语句定义一种对象,Point() 创建一个实例。pass 是空操作,用在这里需要语句块但尚无操作的位置。
type(p) 是 Point,身份比较为 True。类本身也可以被名字引用;默认对象地址或模块显示与执行环境有关,不把它们当成固定预期值。
- 第 11 页 · Instance Attributes 实例属性
本讲的普通类允许通过 p.x = 3 增加实例属性。p.x 与外部变量 x 是不同绑定位置,真实输出为 3、4、100。
先明确点号选择了哪个对象,再谈属性名字。这里没有声称所有 Python 类都支持任意动态属性;特殊限制留到后续机制。
- 第 12 页 · Missing Attributes 缺失属性
先预测哪一次访问成功,哪一次报错。p 和 q 都由同一个类创建,但只有 p 被添加了 x。
不要在这页显示输出。下一页先用实际结果说明 q 缺属性,再解释为什么希望初始化建立共同字段。
- 第 13 页 · Initialization with __init__ 初始化
先回顾上一页:p.x 打印 3,q.x 触发 AttributeError。相同类的实例不自动复制别人的字段。
现在 __init__ 接收新实例,惯用参数名 self。参数 x 是当前调用的局部名字,self.x = x 则给新实例建立属性;y 同理。先解释接收者,再使用代码,不把注解当作验证。
- 第 14 页 · Default Coordinates 默认参数
三个调用依次使用默认或显式参数,真实坐标为 0 0、3 0、3 4。规则与普通函数默认参数相同。
零坐标在本任务中合法,不意味着每个类都应该用零作默认值。参考区会核对旧三角形零边默认状态。
- 第 15 页 · Class Body and Initialization 类体与初始化
先问 class body 和 init 各打印几次。class 语句运行类体,其中 def 建立函数,不立即执行函数体。
这页只呈现源码和问题,实际顺序写在下一页的静态内容中,不留下依赖 JavaScript 才出现的关键答案。
- 第 16 页 · Class Execution and Initialization Results
实际顺序是 class body、init、init。类定义被执行一次,创建两个实例分别初始化。若再次执行 class 语句,类体也会再次运行,不能概括为永远只运行一次。
init 自身返回 None,Point(...) 的结果是实例。错误的非 None 返回与创建钩子在参考区解释,不在主线实现元类。
- 第 17 页 · Aliases and Separate Instances 别名与实例
alias = p 绑定同一个对象,other = Point(3, 4) 则新建对象。通过 alias 将 x 改为 8,p 同样观察到 8,other 仍为 3。
坐标相同不等于一个对象。图的箭头是逻辑引用,不是物理地址;is 的真实结果分别为 True 和 False,沿用 L05 的模型。
- 第 18 页 · Initialization Contract 初始化约定
初始化要说明哪些属性必须建立、哪些初值有效、默认参数是什么,以及失败时发生什么。属性存在和数据合法是两个检查。
Point 的例子用于理解初始化,没有自动验证任意传入对象的数值类型。后半场账户和温度会把状态规则写成显式检查。
- 第 19 页 · II · Instance Methods
已经知道一个实例怎样获得坐标。现在多个点可以共用同一个 show 或 move 实现,但每次调用要明确操作哪一个对象。
首先学习普通实例方法,再比较局部参数、属性与结果。类方法和静态方法暂不混入这些例子。
- 第 20 页 · Method Definitions 方法定义
普通实例方法的第一个参数接收绑定对象。定义写 self,p.show() 选择 p 作为接收者并打印 3 4。
self 是惯用名字,不是关键字。参数规则仍是函数规则;不能把普通实例方法的绑定规则泛化到所有点号调用。
- 第 21 页 · Receiver Binding 接收者绑定
对这个普通 Python 方法,a.show() 可以显式写为 Point.show(a)。函数实现相同,但每次调用有自己的接收者与局部状态。
图中两次调用分别选择 A 和 B,不把两个实例画成各自复制一份方法代码。完整元数据证明放参考区,在这里不先用 __func__。
- 第 22 页 · A Missing Receiver Parameter
函数定义不接收参数,实例调用仍会自动传一个接收者。请先预测发生的是正常打印还是参数错误。
本页不写答案,下一页结合局部参数解释。问题在参数数量,不在函数参数必须拼成 self。
- 第 23 页 · Local Parameters and Attributes 局部与属性
上一页真实 TypeError 表示零参数函数收到了一个实例。改用其他名字的第一参数在语法上可行,省略接收参数才造成不匹配。
这里 shift 的局部 x 是 2,self.x 原来是 3,外部 x 仍为 100,得到 5 100。局部名字和对象属性的绑定位置不同。
- 第 24 页 · One Method, Two Receivers 一个方法与两个接收者
先让学生分别说出 a.show 和 b.show 中 self 指向哪里。一个底层函数通过不同接收者读取不同坐标,真实输出为 0 0、3 4。
每次调用的局部状态独立,不表示实例可达的所有对象都不共享。第四节会区分独立绑定和共享列表。
- 第 25 页 · Point Movement 点的平移
move 将增量加入接收者的两个坐标。a 从 0 0 变为 1 1,b 仍为 3 4。源码包含完整最小定义,独立运行不会借用前页状态。
修改对象与创建新点是不同接口。这里明确原地操作,下一页再核对返回值,不根据方法名猜行为。
- 第 26 页 · State Changes and Return Values 状态与返回值
回收开场题:move 修改原字典的 x 为 4,没有显式 return,因此结果是 None,实际为 4 None。查看第 1 题原分布,不再次提交。
Point.move 使用同样的状态/结果区别。None 不代表调用没有修改数据,数值结果也不证明方法只读;两项都要观察。
- 第 27 页 · Calls Within a Method 方法内调用
普通 message() 选择外部函数,self.message() 选择 Record 的方法,真实输出分别为 global function 和 instance method。
类不会自动把每个裸名字变成 self 的属性。这里先使用明确访问路径,完整 LEGB 规则仍在 L14,不先引入闭包。
- 第 28 页 · Forward Type References 前向类型引用
下一方法需要另一个 Point。在 Python 3.13 执行类体时,类名尚未完成绑定,直接在注解中使用 Point 可能提前求值而报 NameError。
字符串前向引用是本讲主线用法。future 的可选版本信息放参考,不把推迟注解理解为运行时类型校验。
- 第 29 页 · Distance Between Objects 对象间距离
distance_to 从 self 与 other 分别读取坐标,计算差值和距离。本例得到 5.0,不移动两个点。
接口约定查询不修改状态,还应实际核对坐标。几何例子使用尺度适中的有限数值,不声称任意大数都具有数值稳定性。
- 第 30 页 · Quiz 2 · Initialization and Receivers
两题分别检查是否建立实例字段,以及显式普通方法调用选择哪个实例。所有语法已经解释,不提前考类方法或共享类列表。
每题提交一次,下一页按原代码与实际结果解释。不要凭参数名字或最近创建的对象猜接收者。
- 第 31 页 · Quiz Review · Attribute Creation
text.strip 的结果被绑定给局部 text,没有建立 self.text;访问 a.text 得到实际 AttributeError。注解和参数名字不创建字段。
这里核对的是属性是否存在,后面的第 4 题则检查属性初值是否合法,两项不同。查看原题分布,不新发一题。
- 第 32 页 · Quiz Review · Receiver Selection
Counter.add(b, 2) 显式把 b 作为 self。b.value 从 10 更新到 12,a.value 保持 1,实际打印 1 12。
普通实例调用可写 b.add(2),这里的类访问用于把隐含参数说清楚。没有根据变量名或创建顺序选择对象。
- 第 33 页 · The Point Interface Point 接口
把已经学过的 Point 接口集中核对。类调用返回实例,init 本身返回 None;显示、修改与查询是不同操作。
表格描述本实现的约定,不是 Python 自动保证。实际检查状态、输出和返回值,并在讲义中看完整独立程序。
- 第 34 页 · Instance-Method Reasoning 实例方法分析
上半场形成四步分析:找接收者、分清绑定位置、按调用顺序执行、分别观察状态和结果。递归与普通函数的调用规则仍适用。
后半场再问:即使调用过程理解正确,对象状态是否符合约定?这需要显式规则及验证,并不是使用类就已经完成。
- 第 35 页 · Break
在这里进入两个 45 分钟的分界。上半场已经解释对象、初始化、self 和状态/返回值。
后半场从账户的非法操作进入有效状态与封装,再比较类级共享、实例字段和类方法。参考区不计入必讲时间。
- 第 36 页 · III · Encapsulation and State Rules
方法把相关操作组织起来,但错误操作仍可能破坏状态。先写账户任务的单位、输入和规则,再审查候选。
以非负余额为例,初始状态与每个公开更新都要检查。类不是权限边界,直接写属性仍可能绕过约定接口。
- 第 37 页 · The Account Contract 账户约定
先规定金额单位为整数分,初始余额非负,存取金额为正整数。存款返回 None,取款通过 bool 报告成功,拒绝不改变余额和历史。
这是教学模型,不具有审计、货币或并发的生产保证。属性仍可直接赋值,下面的规则仅保证正确使用约定方法的行为。
- 第 38 页 · A Withdrawal Candidate 取款候选
这页明确是有错误的候选。余额为 100,取款 amount 为 -20,先预测原分支会不会拒绝,以及减去负数的结果。
不能因为放在类里就按常识认为它会报错。下一页展示真实结果并修正条件,不在预测页写答案。
- 第 39 页 · Withdrawal Validation 取款检查
旧候选的真实结果为 True、120,原因是只检查余额不足。新版本在更新前拒绝非正金额或余额不足,负取款实际为 False、100。
完整教学账户还检查整数类型,并同时观察历史是否变化。本页是最小独立整数例子,完整程序与非法初值检查在讲义。
- 第 40 页 · Rules at Every Entry Point 入口与规则
验证规则覆盖构造、存款与取款各入口。一个 setter 有检查,不会让构造自动执行相同规则。
拒绝还需要检查没有先修改余额、没有先加入历史。按接受和拒绝路径分别记录原状态、操作、结果与新状态。
- 第 41 页 · Account State Transitions 账户状态变化
真实程序存入 50 后取出 30,余额为 120;过额和负取款都返回 False,余额和历史保留。历史只含两次接受的操作。
第二账户保持余额 0 和空历史。其列表来自独立初始化,不共享类级列表。账单实现用普通循环,不提前使用生成器表达式。
- 第 42 页 · The Temperature Contract 温度约定
先解释 math.isfinite 是有限性检查,再在温度代码中使用。值不能低于绝对零度,构造和更新都需检查。
内部 _celsius 在此首次说明为非公开命名约定,不强制保护。课件只给最小摄氏/华氏接口,实验拓展三种查询,方法名以实验页为准。
- 第 43 页 · Temperature Updates 温度更新
先按已写明的条件预测两次更新:一个低于边界,一个有效。分别观察布尔返回值与保留的数值。
本页明确展示 setter 片段,构造和查询定义在完整讲义。真实答案放下一页,不在预测内容中显示,也不给不完整片段加运行按钮。
- 第 44 页 · Public and Nonpublic Interfaces 公开与非公开接口
先回顾上一页实际为 False 25、True 212.0,拒绝保留旧值,接受后正确更新并转换。构造负温度也应拒绝。
再区分公开接口与内部字段。单下划线说明不稳定实现,语言仍允许访问或写入;封装不是安全沙箱。
- 第 45 页 · Name Mangling 名称改写
双前导下划线在类体发生名称改写,_Secret__hidden 可以读取 42,原拼写触发 AttributeError。这些结果来自实际运行。
这里不使用继承代码。避免子类无意冲突的理由在 L10 继续解释,不能称它为绝对私有访问保护。
- 第 46 页 · Underscore Naming 下划线命名
三种形式不能混为一谈。_x 是非公开约定,__x 在类体中改写名字,__init__ 是文档规定的特殊方法。
任意自造的双端下划线名字不自动具有解释器行为。读写是否被允许与接口是否建议使用也需要分开。
- 第 47 页 · Quiz 3 · Initial-State Rules
本题 setter 有负数检查,但构造直接存入参数。按实际执行判断,不能认为构造自动调用 setter。
这次检查数值是否有效,与第 2 题是否创建属性不同。单下划线已经解释,直接读取内部字段仅作为代码审查手段。
- 第 48 页 · IV · Shared Data and Method Kinds
实例有自己的绑定位置,但两个位置仍可能指向同一个列表。先分析普通类属性查找与赋值,再区分修改对象和建立新绑定。
最后补齐往年的类方法与 cls,不把缺失内容删掉,也不提前展开通用装饰器。
- 第 49 页 · Instance and Class Attributes 实例与类属性
两个 Point 分别保存坐标,dimensions 是类体建立的属性。本例各维度访问都为 2,但 a.x 与 b.x 不同。
不采用国籍或未经核查动物分类的类比。这里的几何例子与主线一致,Dog 原字段更新例子仍在参考区保留。
- 第 50 页 · Ordinary Attribute Lookup 普通属性查找
在本讲没有描述符与继承参与的普通字段例子中,实例缺少同名绑定时可以访问类属性。先预测对 a 的赋值会影响哪些访问。
下一页显示实际结果并区分两种赋值位置,不把简化表当作 Python 的完整查找算法。
- 第 51 页 · Attribute Binding and Mutation 绑定与修改
上一页真实为 only A、class、class,给 a 的绑定没有改类或 b 的访问。普通实例赋值和类赋值的目标不同。
append 则修改已经找到的列表,不自动新建实例字段。下面先按这个区别预测共享篮子的结果。
- 第 52 页 · A Shared Basket List 共享列表
类体只有一次列表构造,add 中 self 选择当前篮子,但 self.items 可能通过类属性找到同一个列表。先预测 b.items 和身份比较。
不要提前显示结果。下一页用真实关系图说明,不把新实例画成隐式复制了集合。
- 第 53 页 · Shared-List References 共享列表引用
实际 b.items 含 apple,a.items is b.items 为 True。两个实例经同一个类属性找到一份列表,append 修改该对象。
共享本身并非语法错误;本任务要求独立篮子,才需要修正。若接口有意登记共有状态,类级集合也可能合理。
- 第 54 页 · Per-Instance Collections 实例集合
把 [] 放进 init,每次初始化执行新列表构造。添加 a 后 b 仍为空,身份比较为 False。
独立性来自实际构造新对象,不来自 self 名字。空列表值可以相等而身份不同,继续沿用 L05 的判断方式。
- 第 55 页 · Shared Input References 输入引用
self.items = items 直接绑定传来的对象。两个构造都传 shared,先预测 b 的内容及两字段是否同一个对象。
这是不同于类级列表的共享来源。下一页先回顾真实结果,再介绍类级计数,不把所有共享都归因于类变量。
- 第 56 页 · An Instance-Creation Counter 创建计数
先回顾上一页:初始化没有复制 shared,b 也看到 apple,身份为 True。需要隔离外层时可以按接口复制,并注意浅拷贝的范围。
这里通过 Student.count 更新类绑定,两个初始化得到 2。计数是创建事件,不是存活对象数;失败初始化应先校验再决定是否计数。
- 第 57 页 · Class Methods and cls 类方法
先明确内置 @classmethod 标记的具体行为:自动参数是类,惯用名 cls,从类访问无需先创建实例。
下页才使用这段语法。本讲不展开高阶函数或一般装饰器原理,那部分仍在 L14;普通实例方法的 self 规则不能套到这里。
- 第 58 页 · Calling a Class Method 类方法调用
先预测未创建和创建后的计数,再说明从 a 访问类方法时 cls 是谁。源码有完整独立定义,计数从这次类体的 0 开始。
答案在下一页静态表中。不是从实例访问就一定传实例,class method 仍绑定类。
- 第 59 页 · Method Categories 方法类别
前页实际为 0、2 2,两种 created_count 访问都将 Student 传给 cls。先显示真实结果再比较方法类别。
这里首次说明静态方法不自动传接收者,完整程序在参考区。小测只考已经展示的类方法和共享,不考未展示的静态实现。
- 第 60 页 · Quiz 4 · Sharing and Class Methods
第 5 题结合类列表与实例遮蔽,第 6 题只检查 cls 绑定。分别按已经教过的规则执行,不能只按关键词做选择。
两题各提交一次,下面保留静态结果解释与原题分布。不重复开场题,也不加入静态方法的新实现。
- 第 61 页 · Quiz Review · Sharing and Binding
第 5 题先给原类列表加入 apple,再给 a 新列表,长度为 0、1、1;b 与 Basket 仍访问原列表。
第 6 题两次类方法访问都给 Sensor.count 增加 1,结果为 2,构造 Sensor 并没有自动执行 bump。查看原分布,不新增提交。
- 第 62 页 · Design Choices 类的设计选择
选择类要根据状态持续、操作关系、有效规则和接口边界判断。普通函数、字典和记录也可能更直接。
一个实例、一个方法或只读数据都不能机械排除类。旧材料中的规模与协作动机保留,未经来源核对的行数与城市类比不使用。
- 第 63 页 · Lab 9 · Design and Verification
保留原六项任务,分为四个基础类、成绩簿重构、设计判断与调试记录。五个代码入口与三张文字卡已经在本地准备,不能把本地完成称为线上提交。
矩形原地 scale 返回 None,空 pop/peek 抛 IndexError,空成绩簿 top_student 返回 None。代码与文字记录分别评分,C 不增分。截止从统一校历读取;需要真实 AI 使用或未使用声明。
- 第 64 页 · Inheritance, Protocols and Modules
回到本讲的问题:已经能为一类状态说明初始化、方法接收者、返回与副作用、公开规则以及共享层次。还需要通过测试验证接口是否实现。
下一讲研究继承、运算协议、多态和模块。这些旧合并课件内容不是被删除,本讲没有提前使用它们。课堂主线到这里结束。
- 第 65 页 · Reference 参考
参考区保留完整实现、更多验证、往年的三角形、Dog、快乐数和向量等内容,不计入本讲必讲时间。
片段页面明确标记并链接完整讲义。输出、异常和数值由实际运行获得,后续 L10 内容仍按范围承接。
- 第 66 页 · Built-in Constructors 内置构造器
int、float、complex、str 与几个容器的空构造有各自默认值。repr 让空字符串可见,__name__ 给出这里的类名。
输出来自当前 3.13,不固定任何 id 或地址。名字重新绑定到另一类对象,不表示原来的对象类型改变。
- 第 67 页 · Class Execution and Object Identity
补充旧材料中类只是等到实例化才使用的误述。执行类体时已经建立类、字段和函数,实例创建又是后续调用。
同坐标两个新 Point 不是同一个对象,别名则引用同一对象。用 True/False 身份关系核对,不复制旧内存地址。
- 第 68 页 · Point · Complete Program
完整 Point 同时提供默认构造、显示、原地平移和距离查询。片子展示距离方法片段,讲义包含完整定义和三次观察。
实际为初始距离 5.0,移动后 1 1,再查询约 3.60555。片段不加运行按钮,不要求先运行其他页面。
- 第 69 页 · Three Sources of Shared Collections
三种情况都可能出现共享,但机制不同:类级列表、一次定义的可变默认对象、重复传入的同一对象。不能全部归因于类变量。
需要隔离时明确是否新建或复制,浅拷贝只隔离外层。各完整例子在讲义独立运行,避免前一段留下的状态干扰。
- 第 70 页 · Triangle · Interface and Validation
完整保留往年三角形的字段、有效性检查、更新、面积与两种打印方法。零边虽然可存进字段,不表示合法三角形,因此正式默认值改为 1。
更新拒绝要保留原三边,area 也检查当前状态,因为直接写公开字段可以绕过 setter。示例只承诺尺度适中的有限数值。
- 第 71 页 · Triangle · Heron's Formula
Heron 公式用半周长 s 计算面积。area 先检查当前字段,不能对无效三角形返回一个虚构面积。
3、4、5 的面积实际为 6;print_area 通过 self.area 使用当前实例的方法。片段和完整讲义入口分开,长类不硬塞进一页。
- 第 72 页 · Triangle · Independent Instances
两个对象使用同一个 area 实现,但分别读取各自三边。实际面积为 6.0 和 3.897114317029974,无效更新后 a 的面积仍为 6。
保留旧例的多个实例、字段访问和方法内调用知识,不沿用源程序旧行号或地址。
- 第 73 页 · Dog · Records and Updates
保留往年 Dog 的四字段、外部 train 函数、直接更新与 setter 接口。没有必要使用出处不明的动物或表情图片。
本例只说明记录组织,不宣称年龄体重已经符合业务规则。setter 这个名字不自动提供检查,需看实现和约定。
- 第 74 页 · Happy Numbers · Steps and Cycles
首步实际为 82、4、570,三个判定依次 True、False、False。19 经过 82、68、100、1,2 则进入包含 4 的循环。
集合用于检测出现过的值,不把集合显示顺序当执行轨迹。这个判定也可用普通函数,不是算法必须采用类。
- 第 75 页 · Happy Numbers · Query Side Effects
旧候选对 19 返回 True 时,number 已变成 100;修正版用局部 current 保留字段 19。这两行由两份实际完整程序运行得到。
只比较 True 会漏掉副作用。保留原数和相关操作是否值得类接口,需要根据任务判断,不声称类是快乐数算法必需。
- 第 76 页 · Vector · Storage and Length
n 维数据存放在标量列表中,构造复制外层。length 用普通循环累计平方和,print_length 只是显示查询结果。
[3,4] 长度实际为 5,空向量和零向量长度为 0。浅拷贝适合本例标量元素,不保证任意嵌套可变对象都独立。
- 第 77 页 · Vector · Dot Product and Scaling
点积要求两个向量维度一致,逐个坐标乘积累加。[3,4] 与 [1,2] 的实际点积为 11。
scale 原地修改分量并返回 None,乘 2 后长度为 10,传入原列表保持。完整定义包含全部方法,片段不单独提供运行按钮。
- 第 78 页 · Vector · Direction Angles 方向角
明确方向角是向量与各坐标轴的夹角列表,单位弧度。先解释反余弦的定义域,再用分量除以长度得到方向余弦。
[3,4] 两个实际角约为 0.9273 和 0.6435;零向量抛 ValueError。钳位用于微小舍入越界,不代表极端数值下的一般稳定性保证。
- 第 79 页 · Namespaces and Function Objects 名称与函数对象
外部 area 与实例 area 通过明确访问路径区分,实例方法取自身字段调用外部函数,两个面积都实际为 6.0。
f = print 绑定函数对象,后续 f 调用正常打印。类不是局部参数隔离的唯一机制,不使用未经核查的超大软件数字强调必要性。
- 第 80 页 · Bound-Method Metadata 绑定方法元数据
先解释 __self__ 与 __func__ 的定义再访问。两次身份比较实际 True、True,保存 a.show 后改变 a.x,f 仍选择同一个实例并打印 8 0。
这组属性针对本例 Python 定义的普通方法,不推广到所有内置方法。完整程序包含 Point 定义,不需要先运行之前页面。
- 第 81 页 · Static and Unbound Calls 静态与显式调用
在第 59 页已说明静态方法不自动传接收者。这里展示完整标记和程序,两种访问实际为 2、7。
没有标记的 add(u,v) 可以显式由 Test.add(1,1) 调用,但实例访问额外传对象导致参数过多。工具函数也可放类外,不把位置当作必须使用类的理由。
- 第 82 页 · Annotations and Initialization Failures
init 返回 1 在 3.13 产生实际 TypeError,init 必须返回 None。误拼初始化方法不会自动运行它,缺接收者则是参数数量问题。
通常 __new__ 创建、__init__ 初始化;不在这里实现创建钩子。字符串前向注解是主线,future 从 3.7 可选且 3.13 仍需显式启用,不把它当类型校验。
- 第 83 页 · Object-Oriented Organization and Alternatives
保留往年 OO 的组织动机和简短历史。公开来源支持 Simula 与 Smalltalk 的影响,不足以声称 OO 在所有领域取代其他范式。
函数、字典、元组与结构化记录仍可满足任务。NamedTuple 只介绍名称和适用性,不提前使用新 API;单实例、单方法或只读数据不是硬判断规则。
- 第 84 页 · Independent Verification 独立核验
围绕一个独立程序核对默认值、初始范围、多个对象和返回值,再分别验证接受与拒绝路径。只看正常样例无法证明独立性或失败原状态。
用本讲普通例子说明验证方法,不公开五道实验完整参考实现。可信教师测试也不能声称已经完成生产安全沙箱验证。
- 第 85 页 · Lab 9 · Interfaces and Edge Cases
实验、骨架和测试采用同一固定接口。五项特别容易混淆的边界在这里集中列出,详细范围与分数以两语实验页为准。
A/B 文字卡有设计和回归的人工分,C 是零分学习记录。声明要对应真实操作,不虚构已经运行或线上提交。
- 第 86 页 · Scope of L09 and L10 本讲与下讲范围
旧合并课件 87 页中,前面的类与实例核心在本讲保留;p33 之后的继承、运算协议、鸭子类型与模块明确由 L10 承接。
没有把复杂内容删除,也没有在开场或测验中使用尚未解释的语法。参考区供查阅,课堂主线与时间安排仍为 64 页。


