- 译者序
- 前言
- 第1章 问答环节
- 第2章 Python 如何运行程序
- 第3章 如何运行程序
- 第4章 介绍 Python 对象类型
- 第5章 数字
- 第6章 动态类型简介
- 第7章 字符串
- 第8章 列表与字典
- 第9章 元组、文件及其他
- 第10章 Python 语句简介
- 第11章 赋值、表达式和打印
- 第12章 if 测试和语法规则
- 第13章 while 和 for 循环
- 第14章 迭代器和解析,第一部分
- 第15章 文档
- 第16章 函数基础
- 第17章 作用域
- 第18章 参数
- 第19章 函数的高级话题
- 第20章 迭代和解析,第二部分
- 第21章 模块:宏伟蓝图
- 第22章 模块代码编写基础
- 第23章 模块包
- 第24章 高级模块话题
- 第25章 OOP:宏伟蓝图
- 第27章 更多实例
- 第28章 类代码编写细节
- 第29章 运算符重载
- 第30章 类的设计
- 第31章 类的高级主题
- 第32章 异常基础
- 第34章 异常对象
- 第35章 异常的设计
- 第36章 Unicode 和字节字符串
- 字符串基础知识
- Python 的字符串类型
- 文本和二进制文件
- Python 3.0 中的字符串应用
- 转换
- 编码 Unicode 字符串
- 编码非ASCII文本
- 编码和解码非ASCII文本
- 其他 Unicode 编码技术
- 转换编码
- 在 Python 2.6 中编码 Unicode 字符串
- 源文件字符集编码声明
- 使用 Python 3.0 Bytes 对象
- 序列操作
- 创建 bytes 对象的其他方式
- 混合字符串类型
- 使用 Python 3.0(和 Python 2.6)bytearray 对象
- 使用文本文件和二进制文件
- Python 3.0 中的文本和二进制模式
- 类型和内容错误匹配
- 使用 Unicode 文件
- 在 Python 3.0 中处理 BOM
- Python 2.6 中的 Unicode 文件
- Python 3.0 中其他字符串工具的变化
- Struct二进制数据模块
- pickle对象序列化模块
- XML解析工具
- 本章小结
- 本章习题
- 习题解答
- 第37章 管理属性
- 第38章 装饰器
- 第39章 元类
- 附录A 安装和配置
- 附录B 各部分练习题的解答
- 作者介绍
- 封面介绍
概览OOP
属性继承搜索
值得庆幸的是,比起C++或Java等其他语言,Python中OOP的理解和使用都很简单。作为动态类型脚本语言,Python把其他工具中让OOP隐藏的语法杂质和复杂性都去掉了。实际上,Python中大多数OOP的故事,都可简化成这个表达式:
本书一直使用这个表达式读取模块的属性,调用对象的方法等。然而,当我们对class语句产生的对象使用这种方式时,这个表达式会在Python中启动搜索——搜索对象连接的树,来寻找attribute首次出现的对象。当类启用时,上边的Python表达式实际上等于下列自然语言。
找出attribute首次出现的地方,先搜索object,然后是该对象之上的所有类,由下至上,由左至右。
换句话来说,取出属性只是简单地搜索“树”而已。我们称这种搜索程序为继承,因为树中位置较低的对象继承了树中位置较高的对象拥有的属性。当从下至上进行搜索时,连接至树中的对象就是树中所有上层对象所定义的所有属性的集合体,直到树的最顶端。
在Python中实际上就是这样。我们通过代码建立连接对象树,而每次使用object.attribute表达式时,Python确实会在运行期间去“爬树”,来搜索属性。为了更具体的说明,图25-1是这种树的一个例子。
图25-1中,包含了五个对象树,而对象都标识为变量,这些对象全都有相应的属性,可进行搜索。更明确地讲,此树把三个类的对象(椭圆的C1、C2以及C3)和两个实例对象(矩形的I1和I2)连接至继承搜索树。注意:在Python对象模型中,类和通过类产生的实例是两种不同的对象类型。
图 25-1 类树,底端有两个实例(I1和I2),在它上有个类(C1),而顶端有两个超类(C2和C3)。所有这些对象都是命名空间(变量的封装),而继承就是由下至上搜索此树,来寻找属性名称所出现的最低的地方。代码隐含了这种树的形状
类
类是实例工厂。类的属性提供了行为(数据以及函数),所有从类产生的实例都继承该类的属性(例如,通过时薪和小时数计算员工薪水的函数)。
实例
代表程序领域中具体的元素。实例属性记录数据,而每个特定对象的数据都不同(例如,一个员工的社会安全号码)。
就搜索树来看,实例从它的类继承属性,而类是从搜索树中所有比它更上层的类中继承属性。
在图25-1中,我们可以按照椭圆形在树中相对的位置再进一步分类。我们通常把树中位置较高的类称为超类(superclass)(就像C2和C3)。树中位置较低的类则称为子类(就像C1)[1]。这些术语指的就是相对于树中位置和角色。超类提供了所有子类共享的行为,但是因为搜索是由下而上,子类可能会在树中较低位置重新定义超类的变量名,从而覆盖超类定义的行为。
最后几句话其实就OOP软件定制的关键之处,让我们扩展这个概念。假设我们创建了图25-1的树,然后说:
这个代码会立即启用继承。因为这是一个object.attribute表达式,于是会触发图25-1中对树的搜索:Python会查看I2和其上的对象来搜索属性w。确切地讲,就是以下面这个顺序搜索连接的对象:
找到首个w之后就会停止搜索(但如果找不到w,就发生一个错误)。此例中,直到搜索C3时才会找到w,因为w只出现在了该对象内。也就是说,通过自动搜索,I2.w会解析为C3.w。就OOP术语而言,I2从C3“继承”了属性w。
最后,这两个实例从如下所示。类中继承了四个属性:w、x、y和z。其他属性的引用则会循着树中其他路径进行。如下所示。
·I1.x和I2.x两者都会在C1中找到x并停止搜索,因为C1比C2位置更低。
·I1.y和I2.y两者都会在C1中找到y,因为这里是y唯一出现的地方。
·I1.z和I2.z两者都会在C2中找到z,因为C2比C3更靠左侧。
·I2.name会找到I2中的name,不需要“爬树”。
通过图25-1的树来跟踪这些搜索,从而可以了解Python中继承搜索的工作方式。
前面的列表中的第一项也许是最需要注意的:因为C1在树中较低的地方重新定义了属性x,相当于有效地取代其上C2中的版本。稍后就会知道,这类重新定义就是OOP中软件定制的重点。通过重新定义和取代属性,C1有效地定制了它从超类中所继承的属性。
[1]在其他书籍中,偶尔也会遇到基类(base class)和派生类(derived class)来描述超类和子类。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论