返回介绍

类装饰器

发布于 2024-01-29 22:24:14 字数 1939 浏览 0 评论 0 收藏 0

函数装饰器已经证明了是如此有用,以至于这一模式在Python 2.6和Python 3.0中扩展为允许类装饰器。类装饰器与函数装饰器密切相关,实际上,它们使用相同的语法和非常相似的编码模式。然而,不是包装单个的函数或方法,类装饰器是管理类的一种方式,或者用管理或扩展类所创建的实例的额外逻辑,来包装实例构建调用。

用法

从语法上讲,类装饰器就像前面的class语句一样(就像前面函数定义中出现的函数装饰器)。在语法上,假设装饰器是返回一个可调用对象的一个单参数的函数,类装饰器语法:

等同于下面的语法——类自动地传递给装饰器函数,并且装饰器的结果返回来分配给类名:

直接的效果就是,随后调用类名会创建一个实例,该实例会触发装饰器所返回的可调用对象,而不是调用最初的类自身。

实现

新的类装饰器使用函数装饰器所使用的众多相同的技术来编码。由于类装饰器也是返回一个可调用对象的一个可调用对象,因此大多数函数和类的组合已经足够了。

尽管先编码,但装饰器的结果是当随后创建一个实例的时候才运行的。例如,要在一个类创建之后直接管理它,返回最初的类自身:

不是插入一个包装器层来拦截随后的实例创建调用,而是返回一个不同的可调用对象:

这样的一个类装饰器返回的可调用对象,通常创建并返回最初的类的一个新的实例,以某种方式来扩展对其接口的管理。例如,下面的实例插入一个对象来拦截一个类实例的未定义的属性:

在这个例子中,装饰器把类的名称重新绑定到另一个类,这个类在一个封闭的作用域中保持了最初的类,并且当调用它的时候,创建并嵌入了最初的类的一个实例。当随后从该实例获取一个属性的时候,包装器的__getattr__拦截了它,并且将其委托给最初的类的嵌入的实例。此外,每个被装饰的类都创建一个新的作用域,它记住了最初的类。在本章后面,我们将用一些更有用的代码来充实这个例子。

就像函数装饰器一样,类装饰器通常可以编写为一个创建并返回可调用的对象的“工厂”函数,或者使用__init__或__call__方法来拦截所有调用操作的类,或者是由此产生的一些组合。工厂函数通常在封闭的作用域引用中保持状态,类通常在属性中保持状态。

支持多个实例

和函数装饰器一样,使用类装饰器的时候,一些可调用对象组合比另一些工作得更好。考虑前面例子的类装饰器的一个如下的无效替代方式:

这段代码处理多个被装饰的类(每个都产生一个新的Decorator实例),并且会拦截实例创建调用(每个运行__call__方法)。然而,和前面的版本不同,这个版本没有能够处理给定的类的多个实例——每个实例创建调用都覆盖了前面保存的实例。最初的版本确实支持多个实例,因为每个实例创建调用产生了一个新的独立的包装器对象。更通俗地说,如下模式中的每一个都支持多个包装的实例:

我们将在本章随后一个更为实用的环境中研究这一现象,然而,在实际中,我们必须小心地正确组合可调用类型以支持自己的意图。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文