- 译者序
- 前言
- 第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 各部分练习题的解答
- 作者介绍
- 封面介绍
元类与类装饰器的关系:第三回合
当这段代码运行的时候,类装饰器把跟踪器函数装饰器应用于每个方法,并且在调用时产生一条跟踪消息(输出和本示例前面的元类版本相同):
注意,类装饰器返回最初的、扩展的类,而不是其包装器层(当返回包装示例对象的时候更为常见)。就像是元类版本一样,我们保留了最初的类的类型——Person的一个实例,而不是某个包装器类的实例。实际上,这个类装饰器只是处理了类创建,实例创建调用根本没有拦截。
这种区别对于需要对实例进行类型测试以产生最初的类而不是包装器的程序有影响。当扩展一个类而不是一个实例的时候,类装饰器可以保持最初的类类型,类的方法不是它们最初的函数,因为它们绑定到了装饰器,但是这在实际中并不重要,并在元类替代方案中也是如此。
还要注意到,和元类版本一样,这种结构不支持每个方法不同的函数装饰器参数,但是,如果它们适用于所有方法的话,可以处理这种参数。例如,要使用这种方法应用计时器装饰器,下面声明行的最后两个中的任何一个就够了,如果类定义的代码和前面一样的话——第一个使用装饰器参数默认,第二个显式地提供了一个参数:
和前面一样,让我们使用这些装饰器行的最后一个,并且在脚本的末尾添加如下代码,以用一种不同的装饰器来测试示例:
同样的输出出现了,对于每个方法,我们针对每次调用和所有调用获取了计时数据,但是,我们已经给计数器装饰器传递了一个不同的标签参数:
正如你所看到的,元类和类装饰器不仅常常可以交换,而且通常是互补的。它们都对于定制和管理类和实例对象,提供了高级但强大的方法,因为这二者最终都允许我们在类创建过程中插入代码。尽管某些高级应用可能用一种方式或另一种方式编码更好,但在很多情况下,我们选择或组合这两种工具的方法,很大程度上取决于你。
“可选的”语言功能
我在本章开始处引用了一句话,提到元类不是99%的Python程序员都感兴趣的,用以强调它们相对难以理解。这句话不是很准确,只是用一个数字来说明。
说这句话的人是我最初使用Python时的一个朋友,并且,我并不是想不公平地嘲笑某人。另外,实际上,在这本书中,对于语言功能的灰色性,我也常常做出这样的表述。
然而问题在于,这样的语句真的只是适用于单独工作的人而且只是那些可能使用他们自己曾经编写的代码的人。只要一个组织中的任何人使用了一项“可选的”高级语言功能,它就不再是可选的——它有效地施加于组织中的每个人身上。对于你在系统中所使用的外部开发的软件来说,也是如此——如果软件的作者使用了一项高级功能,它对你来说完全不再是可选的,因为你必须理解该功能以便使用或修改代码。
这种观察适用于在本章开始处列出的所有高级工具——装饰器、特性、描述符、元类,等等。如果与你一起工作的任何人或任何程序用到了它们,它们自动地变成所需的知识基础的一部分。也就是说,没有什么是真正“可选的”。我们当中的大多数人不会去挑选或选择。
这就是为什么一些Python前辈(包括我自己)有时候悲叹,Python似乎随着时间的流逝变得更大并且更复杂了。由老手添加的新功能似乎已经增加了对初学者的智力障碍。尽管Python的核心思想,例如动态类型和内置类型,基本保持相同。它的高级附加功能,也变成了任何Python程序员所必须阅读的。正因为此,我选择在这里介绍这些主题,尽管在前面的版本中并没介绍它们。如果高级内容就在你必须理解的代码之中,那么省略它们是不可能的。
另外一方面,很多新的学习者可以挑选所需的高级话题。坦率地讲,应用程序员可能会把大多数的时间花在处理库和扩展上,而不是高级的并且有时候颇为不可思议的语言功能上。例如,本书的后续篇《Programming Python》,处理大多数把Python与应用库结合起来完成的任务,例如GUI、数据库以及Web,而不介绍深奥的语言工具。这一增长的优点是,Python已经变得更为强大。当我们用好它的时候,像装饰器或元类这样的工具不仅毫无辩驳的“酷”,而且允许有创意的程序员来构建更为灵活和有用的API供其他程序员使用。正如我们已经看到的,它们也可以为封装和维护问题提供很好的解决方案。
是否使用所需的Python知识的潜在扩展,取决于你。遗憾的是,一个人的技能水平往往默认决定了这个问题——很多高级的程序员喜欢较为高级的工具,并且往往忘记它们对其他阵营的影响。幸运的是,这不是绝对的;好的程序员也理解简单是最好的工程,并且高级工具也应该只在需要的时候使用。对任何编程语言来说,这都是成立的,但是,特别是在像Python这样的语言中,它作为一种扩展工具广泛地展示给新的和初学的程序员。
如果你仍然不接受这一观点,别忘了,有很多Python用户不习惯基本的OOP和类。相信我的判断,我曾经遇到过数以千计这样的人。基于Python的系统需要它们的用户掌握元类、装饰器之间的细微差别,并且可能由此扩展它们的市场预期。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论