Advanced Python Mastery 练习 6.1 详解:用 Structure 基类简化数据结构定义
示例工程教程【免费下载链接】python-masteryAdvanced Python Mastery (course by dabeaz)项目地址https://gitcode.com/gh_mirrors/py/python-mastery点击查看免费下载本篇文章围绕 python-mastery 课程仓库中 练习 6.1 的官方解决方案 展开讲解如何用一段仅十几行的Structure基类把每个类都要手写冗长__init__()的重复劳动压缩成一行_fields声明。读完本文你将掌握基于*args参数约定自动填充实例、自定义__repr__()生成可复现的构造表达式以及用__setattr__()限制非法属性名的完整实现方案并了解如何用它从零重构Stock类。一、问题背景为什么数据类的__init__()是一种重复劳动在课程 练习 6.1 之前的练习中定义一个表示股票的类需要这样手写每个属性的赋值class Stock: def __init__(self, name, shares, price): self.name name self.shares shares self.price price聚焦在__init__()方法上可以发现每增加一个字段就要多写一行self.xxx xxx。如果一个程序里需要定义几十个这样的数据结构代码量会急剧膨胀且极易出错。练习 6.1 的核心目标就是利用 Python 的函数参数传递约定把这个过程彻底自动化。参数传递约定复习Python 函数支持混合使用位置参数和关键字参数 def foo(x, y, z): return x y z foo(1, 2, 3) 6 foo(1, z3, y2) 6也支持用*和**语法展开序列与字典 args (1, 2, 3) foo(*args) 6 kwargs {y: 2, z: 3} foo(1, **kwargs) 6更重要的是函数可以接收任意数量的位置参数或关键字参数 def foo(*args): print(args) foo(1, 2) (1, 2) foo(1, 2, 3, 4, 5) (1, 2, 3, 4, 5) foo() () def bar(**kwargs): print(kwargs) bar(x1, y2) {y: 2, x: 1} bar(x1, y2, z3) {y: 2, x: 1, z: 3} bar() {}可变参数函数正是练习 6.1 简化数据结构的技术基础让__init__接收任意数量的位置参数再按_fields中声明的字段名逐一绑定。二、核心实现 (a)声明式_fields与自动化的__init__解决方案在structure.py中定义了一个基类Structure完整的三个方法合起来对应仓库 Solutions/6_1/structure.py如下# structure.py class Structure: _fields () def __init__(self, *args): if len(args) ! len(self._fields): raise TypeError(Expected %d arguments % len(self._fields)) for name, val in zip(self._fields, args): setattr(self, name, val) def __setattr__(self, name, value): if name.startswith(_) or name in self._fields: super().__setattr__(name, value) else: raise AttributeError(No attribute %s % name) def __repr__(self): return %s(%s) % (type(self).__name__, , .join(repr(getattr(self, name)) for name in self._fields))_fields声明式编程子类不再需要编写任何__init__只需声明字段名元组class Stock(Structure): _fields (name, shares, price) class Date(Structure): _fields (year, month, day)__init__的工作原理def __init__(self, *args): if len(args) ! len(self._fields): raise TypeError(Expected %d arguments % len(self._fields)) for name, val in zip(self._fields, args): setattr(self, name, val)三步完成全部初始化逻辑数量校验*args接收所有位置参数与_fields的长度比对不相等就抛出带准确期望数量的TypeError逐对绑定zip(self._fields, args)把字段名与实参一一配对动态赋值setattr(self, name, val)按名称为实例创建属性。用课程文档中的样例验证 s Stock(GOOG, 100, 490.1) s.name GOOG s.shares 100 s.price 490.1 s Stock(AA, 50) Traceback (most recent call last): ... TypeError: Expected 3 arguments这里有个重要的细节len(args) ! len(self._fields)中self._fields的动态查找意味着即使子类没有显式定义_fields也会继承基类默认的空元组()从而保证Stock()这种零参数调用也能得到一致的错误行为。三、实现 (b)让repr()输出可直接复现的构造表达式默认的repr()会输出__main__.Stock object at 0x...既不可读也无法还原。解决方案为Structure添加__repr__class Structure: ... def __repr__(self): return %s(%s) % (type(self).__name__, , .join(repr(getattr(self, name)) for name in self._fields))关键点拆解type(self).__name__取实际子类的类名Stock而非Structure保证多态环境下显示正确生成器表达式repr(getattr(self, name)) for name in self._fields按声明顺序取出每个字段的repr(), .join(...)拼接参数列表最终产出与构造调用形式一致的字符串。运行效果 s Stock(GOOG, 100, 490.1) s Stock(GOOG,100,490.1)这种可复现表示reproducible representation是repr的良好实践eval(repr(s))应能重建等价对象对调试和日志输出非常有用。四、实现 (c)用__setattr__限制属性名为了让数据结构保持封闭解决方案重写了__setattr__class Structure: ... def __setattr__(self, name, value): if name.startswith(_) or name in self._fields: super().__setattr__(name, value) else: raise AttributeError(No attribute %s % name)两条放行规则其余一律拒绝字段白名单name in self._fields—— 只允许赋值声明过的字段私有属性豁免name.startswith(_)—— 允许任何下划线开头的私有属性如_shares、_internal这类属性常用于内部缓存或派生状态。验证行为 s Stock(GOOG, 100, 490.1) s.shares 50 # 合法在 _fields 中 s.share 50 # 非法拼写错误不在 _fields 中 Traceback (most recent call last): File stdin, line 1, in module File structure.py, line 13, in __setattr__ raise AttributeError(No attribute %s % name) AttributeError: No attribute share s._shares 100 # 私有属性允许这个机制能立即捕获拼写错误如把shares写成share是后续练习引入数据校验validate.py的前置设施。注意super().__setattr__必须显式调用否则会无限递归。五、实现 (d)从零重建Stock类并跑通单元测试在完成前三步后新建stock.py或清空旧代码从零开始# stock.py from structure import Structure class Stock(Structure): _fields (name, shares, price) property def cost(self): return self.shares * self.price def sell(self, nshares): self.shares - nshares新的Stock类只声明字段并补充业务方法cost属性、sell方法完全不再出现__init__。该文件与课程仓库中的 Solutions/6_1/stock.py 实现一致。用单元测试验证重构结果课程要求此时运行teststock.py单元测试源自 练习 5.4 的测试集仓库中的版本见 Solutions/6_1/teststock.py。测试覆盖了test_create/test_create_keyword位置参数与关键字参数创建test_costcost属性计算100 * 490.1 49010.0test_sell卖出操作后股数递减test_reprrepr(s) Stock(GOOG, 100, 490.1)test_bad_attributes.share 100必须抛AttributeError。运行方式cd Solutions/6_1 python3 teststock.py正如练习文档所指出的此时运行测试会有大量失败但至少有一批会通过——因为本阶段的Structure还没有实现关键字参数支持和字段类型校验例如s.shares 50应抛TypeError、s.shares -50应抛ValueError等断言仍无法满足。这些失败恰恰是后续练习的路线图练习 6.2 将引入_init()栈帧技巧解决关键字参数问题后续练习再逐步加入验证器。六、本方案的局限与后续演进在 练习 6.2 中课程明确指出当前实现的三个痛点不支持关键字参数Stock(nameGOOG, shares100, price490.1)会抛出TypeError: __init__() got an unexpected keyword argument pricehelp(Stock)签名无用__init__只有(self, *args)无法显示name, shares, price的友好签名需要额外机制__repr__()与__setattr__()都依赖_fields类之间仍需显式协作。练习 6.2 的解决思路是栈帧黑客利用sys._getframe(1).f_locals读取调用者局部变量把_init做成staticmethodself从局部变量中取出无需作为参数传入从而使Stock(nameGOOG, price490.1, shares50)与help(Stock)均恢复正常。这一演进在仓库 Solutions/6_2/structure.py 中有完整实现可对照阅读。七、小结练习 6.1 展示了 Python 元编程思维的一个经典切片以_fields为声明式接口把初始化、表示、属性管控三件事统一收敛到基类中让子类代码量降到最低。本文所述三段实现__init__自动填充、__repr__可复现输出、__setattr__白名单校验完整对应 soln6_1.md 的官方解答并已用仓库中的 structure.py、stock.py 与 teststock.py 逐行印证。以此为起点读者可以继续阅读 练习 6.2 及其后续练习见证这套Structure框架逐步演进为完整的验证与类型系统。赞分享示例工程教程【免费下载链接】python-masteryAdvanced Python Mastery (course by dabeaz)项目地址https://gitcode.com/gh_mirrors/py/python-mastery点击查看免费下载相关推荐Advanced Python Mastery数据分析NumPy与SciPy基础应用指南Advanced Python Mastery数据分析NumPy与SciPy基础应用指南 想要在Python数据分析领域更上一层楼吗Advanced Pyt示例工程教程大麦抢票脚本怎么跑通从环境配置到参数调优的Python自动化指南大麦抢票脚本怎么跑通从环境配置到参数调优的Python自动化指南 这是一个基于Python的大麦抢票脚本网页端用Selenium驱动Chrome移动端用A示例工程教程Taichi Dataclass 完全指南用 Python 类定义结构化 GPU 数据类型Taichi Dataclass 完全指南用 Python 类定义结构化 GPU 数据类型 Taichi 的 ti.dataclass 装饰器允许开发者用带编程语言编译器高性能计算上一篇CNKI-download3步完成知网文献批量下载的终极自动化工具下一篇SD-PPP终极指南5分钟在Photoshop中实现AI绘图革命创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

MCP for Blender 完整安装指南:用自然语言驱动 Blender 建模

MCP for Blender 完整安装指南:用自然语言驱动 Blender 建模

MCP for Blender 完整安装指南:用自然语言驱动 Blender 建模 【免费下载链接】mcp-for-blender Community plugin to control Blender 3D with any LLM of your choice. Not affiliated with the official Blender Foundation. 项目地址: https://gitcode.com/Git…

2026/10/5 2:10:29 阅读更多 →
Stack-chan Case v1.0(DYNAMIXEL 版)组装指南:XL330 伺服配置、3D 打印外壳与整机装配实战

Stack-chan Case v1.0(DYNAMIXEL 版)组装指南:XL330 伺服配置、3D 打印外壳与整机装配实战

嵌入式物联网智能硬件机器人硬件开发前端AI 应用 【免费下载链接】stack-chan A JavaScript-driven M5Stack-embedded super-kawaii robot. 项目地址: https://gitcode.com/gh_mirrors/sta/stack-chan 点击查看 免费下载 Stack-chan Case v1.0 是 Stack-chan 机器人…

2026/10/5 2:10:29 阅读更多 →
himalaya JMAP 后端在 Fastmail 上的共享命令测试报告:v2.0.0-alpha.1 实测结论与源码级解读

himalaya JMAP 后端在 Fastmail 上的共享命令测试报告:v2.0.0-alpha.1 实测结论与源码级解读

CLI 【免费下载链接】himalaya CLI to manage emails 项目地址: https://gitcode.com/gh_mirrors/hi/himalaya 点击查看 免费下载 本篇技术指南以 himalaya 仓库内真实的 provider 测试报告 cairn/spec/testing/jmap-fastmail.md 为主体,完整解读「跨协…

2026/10/5 2:10:29 阅读更多 →

最新新闻

昇腾部署DeepSeek V3/R1:从MLA/FP8到性能调优的关键实践

昇腾部署DeepSeek V3/R1:从MLA/FP8到性能调优的关键实践

简介:大模型推理部署的难度往往不在模型本身,而在于显存占用与通信效率。以DeepSeek-V3/R1为例,其MLA机制通过潜空间压缩KV Cache,显著降低长上下文下的显存负担;DeepSeekMoE的稀疏激活则有效控制计算量,但…

2026/10/5 2:45:44 阅读更多 →
彻底取消WPS默认打开PDF和Word:从文件关联到防反弹全攻略

彻底取消WPS默认打开PDF和Word:从文件关联到防反弹全攻略

最近好几个同事带着电脑来找我,开口都是同一件事:PDF明明有自己的阅读器,Word文档也明明有Office,可是双击之后,WPS总是“抢跑”。这个“取消wps默认打开pdf和word”的需求,听起来简单,做起来却…

2026/10/5 2:45:44 阅读更多 →
免费企业邮箱搭建:Cloudflare收信、Gmail管理、Resend发送

免费企业邮箱搭建:Cloudflare收信、Gmail管理、Resend发送

这套方案我已经实际跑了快一年,团队几个人共用一个域名邮箱,月成本是零。核心组合就是标题里那三样:Cloudflare、Gmail、Resend,分别管收信、管读信、管发信。如果你是一个独立开发者、一个小工作室,或者只是不想为所谓…

2026/10/5 2:45:44 阅读更多 →
图像传感器深度解析:从CCD到CMOS的信号处理与选型指南

图像传感器深度解析:从CCD到CMOS的信号处理与选型指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 2:45:44 阅读更多 →
Franka Panda七轴协作臂实战:从开箱配置到力控开发详解

Franka Panda七轴协作臂实战:从开箱配置到力控开发详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 2:45:44 阅读更多 →
电影院在线购票系统JavaWeb毕业设计:从环境搭建到核心模块实现

电影院在线购票系统JavaWeb毕业设计:从环境搭建到核心模块实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 2:44:44 阅读更多 →

日新闻

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:22 阅读更多 →
AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

1. 从“plugins”这个词说起:它到底在解决什么问题如果你最近在折腾 AI 编程工具,尤其是 Cursor、Codex CLI、Claude Code 这类带 CLI 的编辑器或命令行助手,那你大概率绕不开一个词——plugins。这个词本身不新鲜,从浏览器到 IDE…

2026/10/5 0:00:23 阅读更多 →
第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:23 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 1:10:22 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 11:40:45 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 20:14:29 阅读更多 →