- 译者序
- 前言
- 第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 各部分练习题的解答
- 作者介绍
- 封面介绍
类通过继承进行定制
在Python中,实例从类中继承,而类继承于超类。以下是属性继承机制的核心观点。
·超类列在了类开头的括号中。要继承另一个类的属性,把该类列在class语句开头的括号中就可以了。含有继承的类称为子类,而子类所继承的类就是其超类。
·类从其超类中继承属性。就像实例继承其类中所定义的属性名一样,类也会继承其超类中定义的所有属性名称。当读取属性时,如果它不存在于子类中,Python会自动搜索这个属性。
·实例会继承所有可读取类的属性。每个实例会从创建它的类中获取变量名,此外,还有该类的超类。寻找变量名时,Python会检查实例,然后是它的类,最后是所有超类。
·每个object.attribute都会开启新的独立搜索。Python会对每个属性取出表达式进行对类树的独立搜索。这包括在class语句外对实例和类的引用(例如,X.attr),以及在类方法函数内对self实例参数属性的引用。方法中的每个self.attr表达式都会开启对self及其上层的类的attr属性的搜索。
·逻辑的修改是通过创建子类,而不是修改超类。在树中层次较低的子类中重新定义超类的变量名,子类就可取代并定制所继承的行为。
这种搜索的结果和主要目的就是,类支持了程序的分解和定制,比迄今为止所见到的其他任何语言工具都要好。另外,这样可以把程序的冗余度降到最低(减少维护成本),也就是把操作分解为单一、共享的实现。此外,这样写程序时,也可让我们对现有的程序代码进行定制,而不是在原地进行修改或是从头开始。
第二个例子
下个例子是建立在上一个例子基础之上的。首先,我们会定义一个新的类SecondClass,继承FirstClass所有变量名,并提供其自己的一个变量名。
SecondClass定义display方法以不同格式打印。定义一个和FirstClass中的属性同名的属性,SecondClass有效地取代其超类内的display属性。
回想一下,继承搜索会从实例往上进行,之后到子类,然后到超类,直到所找的属性名称首次出现为止。在这个例子中,因为SecondClass中的变量名display会在FirstClass内首先被找到,所以SecondClass覆盖了FirstClass中的display。有时候,我们把这种在树中较低处发生的重新定义的、取代属性的动作称为重载。
结果就是SecondClass改变了方法display的行为,把FirstClass特定化了。另外,SecondClass(以及其任何实例)依然会继承FirstClass的setdata方法。用一个例子来说明:
就像往常一样,我们调用Second Class创建了其实例对象。set data依然是执行FirstClass中的版本,但是这一次display属性是来自SecondClass,并打印定制的内容。图26-2描绘了其中涉及的命名空间。
图 26-2 在类树中较低的扩展类中重新定义变量名,从而覆盖了继承的变量名并将其专有化。在这里,SecondClass重新定义了方法display,从而定制了它的实例的display方法
这里有一件和OOP相关的很重要的事情要留意:Second Class引入的专有化完全是在FirstClass外部完成的。也就是说,不会影响当前存在的或未来的FirstClass对象,就像上一个例子中的x:
我们不是修改FirstClass,而是对它进行了定制。很自然,这是有意而为之的例子,但是作为一条规则,因为继承可以让我们像这样在外部组件内(也就是在子类内)进行修改,类所支持的扩展和重用通常比函数或模块更好。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论