返回介绍

新式类的扩展

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

除了钻石继承搜索模式中的这个改变以外(过于罕见,不需要大多数读者留意),新式类还启用了一些更为高级的可能性。下面的小节将对这些额外特性中的每一个给出概览,这些特性在Python 2.6的新式类和Python 3.0的所有类中都可用。

slots实例

将字符串属性名称顺序赋值给特殊的__slots__类属性,新式类就有可能既限制类的实例将有的合法属性集,又能够优化内存和速度性能。

这个特殊属性一般是在class语句顶层内将字符串名称顺序赋值给变量__slots__而设置:只有__slots__列表内的这些变量名可赋值为实例属性。然而,就像Python中的所有变量名,实例属性名必须在引用前赋值,即使是列在__slots__中也是这样。以下是说明的例子。

Slot对于Python的动态特性来说是一种违背,而动态特性要求任何名称都可以通过赋值来创建。这个功能看作是捕捉“打字错误”的方式(对于不在__slots__内的非法属性名做赋值运算,就会侦测出来),而且也是最优化机制。如果创建了很多实例并且只有几个属性是必需的话,那么为每个实例对象分配一个命名空间字典可能在内存方面代价过于昂贵。要节省空间和执行速度(程度对每个程序而言有所不同),slot属性可以顺序存储以供快速查找,而不是为每个实例分配一个字典。

Slot和通用代码

实际上,有些带有slots的实例也许根本没有__dict__属性字典,使得有些书中所写的元程序过于复杂(包括本书中的一些代码)。工具根据字符串名称通用地列出属性或访问属性,例如,必须小心使用比__dict__更为存储中立的工具,例如getattr、setattr和dir内置函数,它们根据__dict__或__slots__存储应用于属性。在某些情况下,两种属性源代码都需要查询以确保完整性。

例如,使用slots的时候,实例通常没有一个属性字典——Python使用第37章介绍的类描述符功能来为实例中的slot属性分配空间。只有slot列表中的名称可以分配给实例,但是,基于slot的属性仍然可以使用通用工具通过名称来访问或设置。在Python 3.0中(以及在Python 2.6中派生自object的类中):

没有一个属性命名空间字典,不可能给不是slots列表中名称的实例来分配新的名称:

然而,通过在__slots__中包含__dict__仍然可以容纳额外的属性,从而考虑到一个属性空间字典的需求。在这个例子中,两种存储机制都用到了,但是,getattr这样的通用工具允许我们将它们当做单独一组属性对待:

然而,想要通用地列出所有实例属性的代码,可能仍然需要考虑两种存储形式,因为dir也返回继承的属性(这依赖于字典迭代器来收集键):

由于两种都可能忽略,更正确的编码方式如下所示(getattr考虑到默认情况):

超类中的多个__slot__列表

然而,注意,这段代码只是解决了由一个实例继承的最低__slots__属性中的slot名称。如果类树中的多个类都有自己的__slots__属性,通用的程序必须针对列出的属性开发其他的策略(例如,把slot名称划分为类的属性,而不是实例的属性)。

slot声明可能出现在一个类树中的多个类中,但是,它们受到一些限制,除非你理解slot作为类级别描述符(这是我们将在本书最后一部分要学习的一种工具)的实现,否则要说明这些限制有些困难:

·如果一个子类继承自一个没有__slots__的超类,那么超类的__dict__属性总是可以访问的,使得子类中的一个__slots__无意义。

·如果一个类定义了与超类相同的slot名称,超类slot定义的名称版本只有通过直接从超类获取其描述符才能访问。

·由于一个__slots__声明的含义受到它出现其中的类的限制,所以子类将有一个__dict__,除非它们也定义了一个__slots__。

·通常从列出实例属性这方面来讲,多类中的slots可能需要手动类树爬升、dir用法,或者把slot名称当做不同的名称领域的政策:

当这种通用性可能的时候,slots可能最好当做类属性来对待,而不是试图让它们表现出与常规类属性一样。要了解关于slots的更多内容,参见Python的标准手册。此外,参见第38章中考虑到基于__slots__和__dict__存储的属性的一个示例。

要了解为什么通用程序可能需要关注slots的一个例子,请参阅上一章的多继承小节中的lister.py显示混入类示例;那里的一个提示描述了示例的slot内容。在这样一个试图通用地列出属性的工具中,slot用法需要额外的代码或者实现相应的政策,以通用地处理基于slot的属性。

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

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

发布评论

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