Python __slots__ 详解:内存优化与性能提升指南

Alice
Alice
发布时间:2026-10-12| 3人浏览过
原创

本文深入解析 Python 中 __slots__ 属性的作用与用法。通过限制类动态添加属性,__slots__ 能有效消除 __dict__ 带来的内存开销,并显著提升属性赋值与访问速度。文章涵盖 __slots__ 在继承中的行为表现、性能对比数据及具体代码示例,帮助开发者在大型应用或内存敏感场景中优化类设计。

简介

参考廖雪峰 Python 教程中的相关描述:

Python 属于动态语言,允许程序在运行期间动态绑定属性或方法(通过 MethodType)。

在实例执行过程中动态绑定的属性和方法,仅对该特定实例生效,其他同类实例无法直接访问这些动态绑定的内容。

若需为所有实例统一绑定属性或方法,可直接对 class 进行绑定操作:

Student.name = ''
Student.set_score = set_score

若使用 ,则仅允许动态绑定 中声明的属性。

例如,尝试绑定未在 中声明的属性会引发报错:

class Student():
__slots__ = ('name', 'age')

S1 = Student()
S1.name = 'Jack' # ok!
S1.score = 123 # error!

起初这可能看似仅有限制作用,但查阅其他资料后发现,该机制能显著节约内存,下文将详细介绍。

允许声明并限定类成员,同时阻止类创建 和 属性,从而节省内存空间。

Python 作为动态语言,普通类的实例可赋值任意属性,这些属性默认存储在 中:

>>> class Student(object):
... pass
... 
>>> Abey = Student()
>>> Abey.name = 'Abey'
>>> Abey.__dict__
{'name': 'Abey'}

这种动态特性主要引发两个问题:

  • 数据通过字典(Hash)存储占用空间较大
  • 难以禁止随意生成类属性

正是解决上述两个问题的方案。通过 属性限定类属性的创建范围:

>>> class Student(object):
... __slots__ = ('name', 'age')
... 
>>> Abey = Student()
>>> Abey.name = 'Abey'
>>> Abey.gender = 'Female'
Traceback (most recent call last):
 File "<input>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'gender'
>>> Abey.__dict__
Traceback (most recent call last):
 File "<input>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__dict__'

定义 变量后, 类实例无法随意创建超出 定义范围的属性(如 gender),且实例中不再存在 结构。

用法

继承树

__slots__ 在继承关系中有两种表现:

  • 子类未声明 时,不继承父类的 ,此时子类实例可随意赋值属性。
  • 子类声明 时,继承父类的 ,此时子类的 为其自身声明加上父类的 。

以下面的父类为例:

>>> class Student(object):
... __slots__ = ('name', 'age')
... 

创建一个未声明 的子类,该实例可创建父类 限定之外的属性 gender:

>>> class SubStudent(Student):
... pass
... 
>>> Bob = SubStudent()
>>> Bob.gender = 'Male'
>>> Bob.__dict__
{'gender': 'Male'}

而创建一个声明了 的子类,其属性只能创建父类 加上自身 限定的属性:

>>> class SubStudent2(Student):
... __slots__ = 'gender'
... 
>>> Cathy = SubStudent2()
>>> Cathy.gender = 'Female'
>>> Cathy.name = 'Cathy'
>>> Cathy.teacher = 'Mrs. Wang'
Traceback (most recent call last):
 File "<input>", line 1, in <module>
AttributeError: 'SubStudent2' object has no attribute 'teacher'

注意:子类的 本身已继承自父类,无需重复声明父类已存在的属性。例如上例中,若重复声明会额外占用内存空间:

>>> class SubStudent3(Student):
... __slots__ = ('name', 'age', 'gender')
... 
>>> from sys import getsizeof
>>> getsizeof(Student()), getsizeof(SubStudent2()), getsizeof(SubStudent3())
(56, 64, 80)

性能对比

我们为何要使用 ?

更快速地赋值属性

参考 Stack Overflow 回答中提供的数据:

import timeit

class Foo(object): __slots__ = 'foo',

class Bar(object): pass

slotted = Foo()
not_slotted = Bar()

def get_set_delete_fn(obj):
 def get_set_delete():
 obj.foo = 'foo'
 obj.foo
 del obj.foo
 return get_set_delete

测试结果显示:

>>> min(timeit.repeat(get_set_delete_fn(slotted))) 0.2846834529991611 >>> min(timeit.repeat(get_set_delete_fn(not_slotted))) 0.3664822799983085

在相同环境(Ubuntu)下, 为 Python3.5 带来了接近 30% 的赋值速度提升:

节约内存空间

>>> 0.3664822799983085 / 0.2846834529991611
1.2873325658284342

由于不使用 存储对象属性, 在特定场景下能节约大量内存空间。具体数据可参考回答链接,此处不再赘述。

参考

[1] Usage of __slots__? , Aaron Hall, Stack Overflow

推荐阅读

[1] Data model , Python Document

[2] python __slots__ 使你的代码更加节省内存 , david_bj, 51CTO

[3] 使用__slots__ , 廖雪峰

总结

以上就是本文的全部内容,希望对大家的学习或工作具有参考价值。如有疑问欢迎留言交流,感谢支持。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。