- 译者序
- 前言
- 第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 各部分练习题的解答
- 作者介绍
- 封面介绍
新式类变化
类和类型合并
类现在就是类型,并且类型现在就是类。实际上,这二者基本上是同义词。type(I)内置函数返回一个实例所创建自的类,而不是一个通用的实例类型,并且,通常是和I.__class__相同的。此外,类是type类的实例,type可能子类化为定制类创建,并且所有的类(以及由此所有的类型)继承自object。
继承搜索顺序
多继承的钻石模式有一种略微不同的搜索顺序,总体而言,它们可能先横向搜索再纵向搜索,并且先宽度优先搜索,再深度优先搜索。
针对内置函数的属性获取
__getattr__和__getattribute__方法不再针对内置运算的隐式属性获取而运行。这意味着,它们不再针对__X__运算符重载方法名而调用,这样的名称搜索从类开始,而不是从实例开始。
新的高级工具
新式类有一组新的类工具,包括slot、特性、描述符和__getattribute__方法。这些工具中的大多数都有非常特定的工具构建目的。
我们在第27章的边栏部分简单地介绍了这些变化中的3个,并且,我们将在第37章的属性管理介绍中以及第38章的私有性装饰器介绍中更深入地回顾它们。由于上面列出的第1个变化和第2个变化可能影响到已有的Python 2.X代码,让我们在介绍新式类之前,更详细地看看这些工具。
类型模式变化
在新式类中,类型和类的区别已经完全消失了。类自身就是类型:type对象产生类作为自己的实例,并且类产生它们的类型的实例。实际上,像列表和字符串这样的内置类型和编写为类的用户定义类型之间没有真正的区别。这就是为什么我们可以子类化内置类型,就像本章前面所介绍的那样,由于子类化一个列表这样的内置类型,会把一个类变为新式的,因此,它变成了一个用户定义的类型。
除了允许子类化内置类型,还有一点变得非常明显的情况,就是当我们进行显式类型测试的时候。使用Python 2.6的经典类,一个类实例的类型是一个通用的“实例”,但是,内置对象的类型要更加特定:
但是,对于Python 2.6中的新式类,一个类实例的类型是它所创建自的类,因为类直接是用户定义的类型——实例的类型是它的类,并且,用户定义的类的类型与一个内置对象类型的类型相同。类现在有一个_class__属性,因为它们也是type的实例:
对于Python 3.0中的所有类都是如此,因为所有的类自动都是新式的,即便它们没有显式的超类。实际上,内置类型和用户定义类型之间的区分,在Python 3.0中消失了:
正如你所看到的,在Python 3.0中,类就是类型,但是,类型也是类。从技术上讲,每个类都由一个元类生成——元类是这样的一个类,它要么是type自身,要么是它定制来扩展或管理生成的类的一个子类。除了影响到进行类型测试的代码,这对于工具开发者来说,是一个重要的钩子。我们将在本章后面讨论元类,并且将在第39章再次详细介绍它。
类型测试的隐含意义
除了提供内置类型定制和元类钩子,新的类模式中类和类型的融合,可能会影响到进行类型测试的代码。例如,在Python 3.0中,类实例的类型直接而有意义地比较,并且以与内置类型对象同样的方式进行。下面的代码源自于这样的一个事实:类现在是类型,并且一个实例的类型是该实例的类。
对于Python 2.6或更早版本中的经典类,比较实例类型几乎是无用的,因为所有的实例都具有相同的“实例”类型。要真正地比较类型,必须要比较实例__class__属性(如果你关注可移植性,这在Python 3.0中也有效,但在那里不是必需的):
并且,正如你所期待的,在这方面,Python 2.6中的新式类与Python 3.0中的所有类同样地工作——比较实例类型会自动地比较实例的类:
当然,正如我们在本书中多次指出的,类型检查通常在Python程序中是错误的事情(我们编写对象接口,而不是编写对象类型),并且更加通用的isinstance内置函数很可能是你在极少数情况下(即必须查询实例类的类型的情况下)想要使用的。然而,知道Python的类型模型的知识,通常对于了解类模型有帮助。
所有对象派生自object
新式类模式中的另一个类型变化是,由于所有的类隐式地或显式地派生自(继承自)类object,并且,由于所有的类型现在都是类,所以每个对象都派生自object内置类,不管是直接地或通过一个超类。考虑Python 3.0中的如下交互模式(在Python 2.6中编写一个显式的object超类,会有等价的效果):
和前面一样,一个类实例的类型就是它所产生自的类,并且,一个类的类型就是type类,因为类和类型都融合了。确实是这样,但是,实例和类都派生自内置的object类,因此,每个类都有一个显式或隐式的超类:
对于列表和字符串这样的内置类型来说,也是如此,因为在新模式中,类型是类——内置类型现在也是类,并且它们的实例也派生自object:
实际上,类型自身派生自object,并且object派生自type,即便二者是不同的对象——一个循环的关系覆盖了对象模型,并由此导致了这样一个事实:类型是生成类的类。
实际上,这种模式导致了比前面的经典类的类型/类区分的几个特殊情况,并且,它允许我们编写假设并使用一个object超类的代码。我们将在本书稍后看到示例,现在,让我们继续介绍其他的新式类变化。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论