0Pricing
Python Academy · 课时

__slots__ 与内存优化

使用 __slots__ 减少每个实例的内存开销。

__slots__ 与内存优化 是 CoddyKit 上的免费 Python Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Python Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Python Academy 课程共包含 4 节课。

默认的 __dict__ 开销

默认情况下,每个 Python 实例都会将属性存储在 __dict__ 字典中,每个实例通常会产生 200–400 字节的显著内存开销。

import sys

class Point:
    def __init__(self, x, y): self.x, self.y = x, y

p = Point(1, 2)
print(sys.getsizeof(p.__dict__))   # ~200 bytes

声明 __slots__

将 __slots__ 定义为属性名称序列。Python 会分配固定大小的数组,而不是字典,从而节省内存。

class SlottedPoint:
    __slots__ = ("x", "y")

    def __init__(self, x, y):
        self.x = x
        self.y = y

p = SlottedPoint(1, 2)
print(p.x, p.y)   # 1 2
# p.z = 3   # AttributeError: no __dict__

节省内存

使用 __slots__ 时,与基于字典的实例相比,每个实例通常可节省 30%–50% 的内存——在创建数百万个对象时,这一节省十分可观。

import sys

class Reg:
    def __init__(self, x, y): self.x, self.y = x, y

class Slotted:
    __slots__ = ("x","y")
    def __init__(self, x, y): self.x, self.y = x, y

print(sys.getsizeof(Reg(1,2)))      # ~56 bytes + ~200 dict
print(sys.getsizeof(Slotted(1,2)))  # ~56 bytes (no dict)

默认没有 __dict__

使用 __slots__ 的类没有 __dict__,因此创建实例后无法添加任意属性。

class Config:
    __slots__ = ("host", "port")
    def __init__(self, h, p): self.host, self.port = h, p

c = Config("localhost", 8080)
# c.debug = True   # AttributeError
print(hasattr(c, "__dict__"))   # False

使用 __slots__ 保留 __dict__

将 "__dict__" 包含在 __slots__ 中,可以在预先声明常用属性为插槽的同时,保留每个实例的字典。

class Hybrid:
    __slots__ = ("x", "__dict__")

    def __init__(self, x):
        self.x = x

h = Hybrid(1)
h.extra = "dynamic"   # allowed
print(h.extra)

__slots__ 中的 __weakref__

使用 __slots__ 的类会失去弱引用支持。将 "__weakref__" 添加到 __slots__ 中即可重新启用该支持。

import weakref

class Node:
    __slots__ = ("value", "__weakref__")
    def __init__(self, v): self.value = v

n = Node(42)
ref = weakref.ref(n)
print(ref())  # <Node object>

继承与 __slots__

如果父类不使用 __slots__,子类仍会获得一个 __dict__。要实现完整的内存节省,整个继承层次结构都必须定义 __slots__。

class Base:
    __slots__ = ("x",)

class Child(Base):
    __slots__ = ("y",)   # no __dict__

class WithoutSlots(Base):
    pass   # gets __dict__ from object

内存基准测试

使用 tracemalloc 或 pympler,测量添加 __slots__ 前后的实际内存使用量。

import tracemalloc

tracemalloc.start()
points = [SlottedPoint(i, i) for i in range(100_000)]
current, peak = tracemalloc.get_traced_memory()
tracemalloc.stop()
print(f"Peak: {peak/1024/1024:.1f} MB")

__slots__ 与对象序列化

使用 __slots__ 的对象可以进行序列化:您可以定义 __getstate__ 和 __setstate__,也可以使用从 Python 3 开始能够自动处理插槽的默认序列化协议。

import pickle

class Point:
    __slots__ = ("x", "y")
    def __init__(self, x, y): self.x, self.y = x, y

p = Point(3, 4)
data = pickle.dumps(p)
p2 = pickle.loads(data)
print(p2.x, p2.y)   # 3 4

带有 __slots__ 的数据类——Python 3.10+

将 slots=True 传给 @dataclass,即可自动生成 __slots__。

from dataclasses import dataclass

@dataclass(slots=True)
class Vector:
    x: float
    y: float

v = Vector(1.0, 2.0)
print(v.x, v.y)   # 1.0 2.0
print(hasattr(v, "__dict__"))   # False

何时使用 __slots__

在以下情况下使用 __slots__:创建数百万个实例、内存受限,或属性访问速度至关重要。如果是通用类且灵活性更重要,则不要使用它。

# Good candidates:
# - Nodes in a large graph or tree
# - Records in a large dataset
# - High-frequency event objects

# Bad candidates:
# - Configuration objects added to ad-hoc
# - Classes that mix-in dynamic attributes

快速检查

在使用 __slots__ 的实例上,尝试设置未列于其中的属性时会发生什么?

回顾

__slots__ 用固定大小的数组替代每个实例的 __dict__,可节省 30%–50% 的内存。如果需要字典或弱引用支持,请包含 "__dict__" 或 "__weakref__"。要实现完整的内存节省,整个继承链都必须使用 __slots__。在 Python 3.10+ 中,可使用 @dataclass(slots=True)。

常见问题解答

「__slots__ 与内存优化」课时是免费的吗?

是的 — 「__slots__ 与内存优化」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Python Academy 课程的其余内容,请升级到 CoddyKit PRO。 Python Academy 课程共包含 4 节课。

「__slots__ 与内存优化」这节课中我会学到什么?

使用 __slots__ 减少每个实例的内存开销。 你通过在浏览器中直接运行的动手代码来练习 Python Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Python Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Python Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「__slots__ 与内存优化」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Python Academy 课中编写并运行代码吗?

能。每节 Python Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. Python 类的创建方式
  2. 编写自定义元类
  3. 描述器:__get__、__set__、__delete__
  4. __slots__ 与内存优化
← 返回 Python Academy