python - 为什么使用描述符可以引入 __slots__?
问题描述
在“Python 的历史”系列的这篇博文中,Guido van Rossum 指出:
描述符的另一个增强功能是在类中引入了 __slots__ 属性。
我将这句话理解为:在引擎盖下 __slots__ 是由描述符实现的。
但与我的解释相反,Guido van Rossum 后来写了几行:
在幕后,此功能的实现完全在 C 中完成,并且非常高效。
那么,__slots__ 不是由描述符实现的吗?
但两句话之后,他又写道:
__slots__ 不仅是描述符的有趣应用,...
那么,__slots__ 和描述符的实际情况是什么?
__slots__ 是否由描述符实现?如果是的话:如何?
解决方案
这些陈述并不自相矛盾。定义的属性__slots__
是所创建类的描述符,并且该描述符的实现是用 C 编写的(假设是 CPython)。
描述符类被调用member_descriptor
,从这个示例代码可以看出:
import inspect
class Test:
__slots__ = 'a',
def __init__(self, a):
self.a = a
type(Test.a) # member_descriptor
inspect.isdatadescriptor(Test.a) # True
inspect.ismemberdescriptor(Test.a) # True
在 GitHub 上的 CPython 存储库上快速搜索发现了它的 C 实现(CPython 版本 3.8.0 的链接)。
更详细一点:
Python 类本质上是一个dict
带有(很多)花里胡哨的东西。另一方面,有一些 Python-C 类使用 C-struct
来实现 Python 类。这样的 C 结构比字典更快并且需要(显着)更少的内存,即使它只包含 Python 对象(基本上是一个包含对 Python 对象的引用的 C 数组)。
为了使“普通”Python 类可以受益于更快的访问和减少的内存占用__slots__
。一个类__slots__
将本质上转换为一个 C 结构。然而,为了使属性查找/设置/删除映射到相应的struct
成员成为可能,需要某种翻译层(描述符)。中定义的成员的翻译层__slots__
是member_descriptor
.
__slots__
因此,当您在-class的实例上查找属性时,您将获得 amember_descriptor
并且member_descriptor
它将知道如何获取/设置/删除基础 C- 的成员struct
。
推荐阅读
- rust - 如何为 Rust Cargo 依赖模块选择 C/C++ 编译器
- python-3.x - python中的并发循环
- python - 如何更正这一行的缩进?
- visual-studio-code - 无法更改 VS Code 字体系列
- ubuntu - 试图将 metasploit 连接到数据库,用户名无处可寻
- ios - SwiftUI:输入字段键盘动画导致选项卡视图中的其他视图动画
- python - 将一个序列化器字段添加到另一个 -django rest 框架
- c# - 在 GAC 中安装 Microsoft.SqlServer.Types
- user-interface - 如何在 Swift UI 中证明文本的合理性?
- reactjs - Ant Design Calendar `onSelect` 无法按预期工作