- 译者序
- 前言
- 第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 各部分练习题的解答
- 作者介绍
- 封面介绍
类装饰器
用法
从语法上讲,类装饰器就像前面的class语句一样(就像前面函数定义中出现的函数装饰器)。在语法上,假设装饰器是返回一个可调用对象的一个单参数的函数,类装饰器语法:
等同于下面的语法——类自动地传递给装饰器函数,并且装饰器的结果返回来分配给类名:
直接的效果就是,随后调用类名会创建一个实例,该实例会触发装饰器所返回的可调用对象,而不是调用最初的类自身。
实现
新的类装饰器使用函数装饰器所使用的众多相同的技术来编码。由于类装饰器也是返回一个可调用对象的一个可调用对象,因此大多数函数和类的组合已经足够了。
尽管先编码,但装饰器的结果是当随后创建一个实例的时候才运行的。例如,要在一个类创建之后直接管理它,返回最初的类自身:
不是插入一个包装器层来拦截随后的实例创建调用,而是返回一个不同的可调用对象:
这样的一个类装饰器返回的可调用对象,通常创建并返回最初的类的一个新的实例,以某种方式来扩展对其接口的管理。例如,下面的实例插入一个对象来拦截一个类实例的未定义的属性:
在这个例子中,装饰器把类的名称重新绑定到另一个类,这个类在一个封闭的作用域中保持了最初的类,并且当调用它的时候,创建并嵌入了最初的类的一个实例。当随后从该实例获取一个属性的时候,包装器的__getattr__拦截了它,并且将其委托给最初的类的嵌入的实例。此外,每个被装饰的类都创建一个新的作用域,它记住了最初的类。在本章后面,我们将用一些更有用的代码来充实这个例子。
就像函数装饰器一样,类装饰器通常可以编写为一个创建并返回可调用的对象的“工厂”函数,或者使用__init__或__call__方法来拦截所有调用操作的类,或者是由此产生的一些组合。工厂函数通常在封闭的作用域引用中保持状态,类通常在属性中保持状态。
支持多个实例
和函数装饰器一样,使用类装饰器的时候,一些可调用对象组合比另一些工作得更好。考虑前面例子的类装饰器的一个如下的无效替代方式:
这段代码处理多个被装饰的类(每个都产生一个新的Decorator实例),并且会拦截实例创建调用(每个运行__call__方法)。然而,和前面的版本不同,这个版本没有能够处理给定的类的多个实例——每个实例创建调用都覆盖了前面保存的实例。最初的版本确实支持多个实例,因为每个实例创建调用产生了一个新的独立的包装器对象。更通俗地说,如下模式中的每一个都支持多个包装的实例:
我们将在本章随后一个更为实用的环境中研究这一现象,然而,在实际中,我们必须小心地正确组合可调用类型以支持自己的意图。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论