- 前言
- 目标读者
- 非目标读者
- 本书的结构
- 以实践为基础
- 硬件
- 杂谈:个人的一点看法
- Python 术语表
- Python 版本表
- 排版约定
- 使用代码示例
- 第一部分 序幕
- 第 1 章 Python 数据模型
- 第二部分 数据结构
- 第 2 章 序列构成的数组
- 第 3 章 字典和集合
- 第 4 章 文本和字节序列
- 第三部分 把函数视作对象
- 第 5 章 一等函数
- 第 6 章 使用一等函数实现设计模式
- 第 7 章 函数装饰器和闭包
- 第四部分 面向对象惯用法
- 第 8 章 对象引用、可变性和垃圾回收
- 第 9 章 符合 Python 风格的对象
- 第 10 章 序列的修改、散列和切片
- 第 11 章 接口:从协议到抽象基类
- 第 12 章 继承的优缺点
- 第 13 章 正确重载运算符
- 第五部分 控制流程
- 第 14 章 可迭代的对象、迭代器和生成器
- 14.1 Sentence 类第1版:单词序列
- 14.2 可迭代的对象与迭代器的对比
- 14.3 Sentence 类第2版:典型的迭代器
- 14.4 Sentence 类第3版:生成器函数
- 14.5 Sentence 类第4版:惰性实现
- 14.6 Sentence 类第5版:生成器表达式
- 14.7 何时使用生成器表达式
- 14.8 另一个示例:等差数列生成器
- 14.9 标准库中的生成器函数
- 14.10 Python 3.3 中新出现的句法:yield from
- 14.11 可迭代的归约函数
- 14.12 深入分析 iter 函数
- 14.13 案例分析:在数据库转换工具中使用生成器
- 14.14 把生成器当成协程
- 14.15 本章小结
- 14.16 延伸阅读
- 第 15 章 上下文管理器和 else 块
- 第 16 章 协程
- 第 17 章 使用期物处理并发
- 第 18 章 使用 asyncio 包处理并发
- 第六部分 元编程
- 第 19 章 动态属性和特性
- 第 20 章 属性描述符
- 第 21 章 类元编程
- 结语
- 延伸阅读
- 附录 A 辅助脚本
- Python 术语表
- 作者简介
- 关于封面
20.7 延伸阅读
除了语言参考手册中必读的“Data model”一章,Raymond Hettinger 写的“Descriptor HowTo Guide”也值得一读——这是 Python 官方文档 HowTo 合集中的一篇。
对 Python 对象模型相关的话题来说,Alex Martelli 写的《Python 技术手册(第 2 版)》一书虽然有点过时,但仍然提供了权威且客观的论述:本章讨论的关键机制在 Python 2.2 中引入,远在那本书涵盖的 2.5 版之前。Martelli 还做了一次题为“Python's Object Model”的演讲,深入探讨了特性和描述符 [ 幻灯片,视频],强烈推荐观看。
至于针对 Python 3 的实例,David Beazley 与 Brian K. Jones 的《Python Cookbook(第 3 版)中文版》一书中有很多说明描述符的诀窍,推荐阅读的有“6.12 读取嵌套型和大小可变的二进制结构”“8.10 让属性具有惰性求值的能力”“8.13 实现一种数据模型或类型系统”和“9.9 把装饰器定义成类”。最后一个诀窍解决了函数装饰器、描述符和方法之间相互作用的深层次问题,说明了如何使用有 __call__ 方法的类实现函数装饰器;如果既想装饰方法又想装饰函数,还要实现 __get__ 方法。
杂谈
self 的问题
“变糟更好”(“Worse is Better”)是Richard P. Gabriel 在“The Rise of Worse is Better”一文中提出的设计思想。这个思想的第一要义是“简单”;对此,Gabriel 说道:
设计方式必须简单,对实现和接口来说都应如此。简单的实现比简单的接口更重要。简单是设计过程中最重要的考虑因素。
我认为,Python 要求明确把方法的第一个参数声明为 self 是“变糟更好”思想的体现。这样,实现是简单了(甚至也优雅了),但却牺牲了用户接口:方法的签名——例如 def zfill(self, width):——在外观上与 pobox.zfill(8) 调用不匹配。
这种做法(以及使用 self 这个标识符)由 Modula-3 语言创造,但是与 Python 有差异:在 Modula-3 中,接口的声明与实现是分开的,而且在接口声明中会省略 self 参数,因此对用户来说,接口声明中的方法显示的参数数量与真正接受的参数数量完全一致。
在这方面,Python 有一项改进——错误消息。对于用户定义的单参数(除 self 之外)方法来说,如果用户调用 obj.meth(),Python 2.7 会抛出异常,显示 TypeError: meth() takes exactly 2 arguments (1 given);不过在 Python 3.4 中,错误消息没那么难以理解了,解决了参数数量问题,还指出了缺失的参数:meth() missing 1 required positional argument: 'x'。
除了要明确把 self 作为参数之外,限制必须使用 self 访问实例属性也备受批评。8 我自己并不介意输入 self 限定符,这样便于把局部变量和属性区分开。我介意的是在 def 语句中使用 self。但是我已经习惯了。
如果讨厌 Python 要求显式使用 self,可以想想 JavaScript 中隐式的 this 那变幻莫测的语义,这样感觉就会好多了。像这样使用self 有一些合理之处,Guido 在他的博客 The History of Python 中写了一篇文章,题为“Adding Support for User-defined Classes”,说明了这些原因。
8例如,A. M. Kuchling 发表的著名文章“Python Warts”(存档)。Kuchling 自己并不讨厌 self 限定符,但是他提到了这一点——可能是为了呼应 comp.lang.python 邮件列表中的观点。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论