返回介绍

元类与类装饰器的关系:第三回合

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

类装饰器也与元类有交叉。如下的版本,用一个类装饰器替换了前面的示例中的元类。它定义并使用一个类装饰器,该装饰器把一个函数装饰器应用于一个类的所有方法。然而,前一句话听起来更像是禅语而不像是技术说明,这所有的工作相当自然——Python的装饰器支持任意的嵌套和组合:

当这段代码运行的时候,类装饰器把跟踪器函数装饰器应用于每个方法,并且在调用时产生一条跟踪消息(输出和本示例前面的元类版本相同):

注意,类装饰器返回最初的、扩展的类,而不是其包装器层(当返回包装示例对象的时候更为常见)。就像是元类版本一样,我们保留了最初的类的类型——Person的一个实例,而不是某个包装器类的实例。实际上,这个类装饰器只是处理了类创建,实例创建调用根本没有拦截。

这种区别对于需要对实例进行类型测试以产生最初的类而不是包装器的程序有影响。当扩展一个类而不是一个实例的时候,类装饰器可以保持最初的类类型,类的方法不是它们最初的函数,因为它们绑定到了装饰器,但是这在实际中并不重要,并在元类替代方案中也是如此。

还要注意到,和元类版本一样,这种结构不支持每个方法不同的函数装饰器参数,但是,如果它们适用于所有方法的话,可以处理这种参数。例如,要使用这种方法应用计时器装饰器,下面声明行的最后两个中的任何一个就够了,如果类定义的代码和前面一样的话——第一个使用装饰器参数默认,第二个显式地提供了一个参数:

和前面一样,让我们使用这些装饰器行的最后一个,并且在脚本的末尾添加如下代码,以用一种不同的装饰器来测试示例:

同样的输出出现了,对于每个方法,我们针对每次调用和所有调用获取了计时数据,但是,我们已经给计数器装饰器传递了一个不同的标签参数:

正如你所看到的,元类和类装饰器不仅常常可以交换,而且通常是互补的。它们都对于定制和管理类和实例对象,提供了高级但强大的方法,因为这二者最终都允许我们在类创建过程中插入代码。尽管某些高级应用可能用一种方式或另一种方式编码更好,但在很多情况下,我们选择或组合这两种工具的方法,很大程度上取决于你。

“可选的”语言功能

我在本章开始处引用了一句话,提到元类不是99%的Python程序员都感兴趣的,用以强调它们相对难以理解。这句话不是很准确,只是用一个数字来说明。

说这句话的人是我最初使用Python时的一个朋友,并且,我并不是想不公平地嘲笑某人。另外,实际上,在这本书中,对于语言功能的灰色性,我也常常做出这样的表述。

然而问题在于,这样的语句真的只是适用于单独工作的人而且只是那些可能使用他们自己曾经编写的代码的人。只要一个组织中的任何人使用了一项“可选的”高级语言功能,它就不再是可选的——它有效地施加于组织中的每个人身上。对于你在系统中所使用的外部开发的软件来说,也是如此——如果软件的作者使用了一项高级功能,它对你来说完全不再是可选的,因为你必须理解该功能以便使用或修改代码。

这种观察适用于在本章开始处列出的所有高级工具——装饰器、特性、描述符、元类,等等。如果与你一起工作的任何人或任何程序用到了它们,它们自动地变成所需的知识基础的一部分。也就是说,没有什么是真正“可选的”。我们当中的大多数人不会去挑选或选择。

这就是为什么一些Python前辈(包括我自己)有时候悲叹,Python似乎随着时间的流逝变得更大并且更复杂了。由老手添加的新功能似乎已经增加了对初学者的智力障碍。尽管Python的核心思想,例如动态类型和内置类型,基本保持相同。它的高级附加功能,也变成了任何Python程序员所必须阅读的。正因为此,我选择在这里介绍这些主题,尽管在前面的版本中并没介绍它们。如果高级内容就在你必须理解的代码之中,那么省略它们是不可能的。

另外一方面,很多新的学习者可以挑选所需的高级话题。坦率地讲,应用程序员可能会把大多数的时间花在处理库和扩展上,而不是高级的并且有时候颇为不可思议的语言功能上。例如,本书的后续篇《Programming Python》,处理大多数把Python与应用库结合起来完成的任务,例如GUI、数据库以及Web,而不介绍深奥的语言工具。这一增长的优点是,Python已经变得更为强大。当我们用好它的时候,像装饰器或元类这样的工具不仅毫无辩驳的“酷”,而且允许有创意的程序员来构建更为灵活和有用的API供其他程序员使用。正如我们已经看到的,它们也可以为封装和维护问题提供很好的解决方案。

是否使用所需的Python知识的潜在扩展,取决于你。遗憾的是,一个人的技能水平往往默认决定了这个问题——很多高级的程序员喜欢较为高级的工具,并且往往忘记它们对其他阵营的影响。幸运的是,这不是绝对的;好的程序员也理解简单是最好的工程,并且高级工具也应该只在需要的时候使用。对任何编程语言来说,这都是成立的,但是,特别是在像Python这样的语言中,它作为一种扩展工具广泛地展示给新的和初学的程序员。

如果你仍然不接受这一观点,别忘了,有很多Python用户不习惯基本的OOP和类。相信我的判断,我曾经遇到过数以千计这样的人。基于Python的系统需要它们的用户掌握元类、装饰器之间的细微差别,并且可能由此扩展它们的市场预期。

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

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

发布评论

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