Python 的 __slots__ 和数据类的(内存方面和访问时间方面)比较是什么
What is the (memory-wise and access-time-wise) comparison of Python's __slots__ and dataclasses
Python 的 __slots__
用于减少实例的内存占用,这是通过在 "small fixed-sized array[s], much like a tuple or a list" 中存储变量来实现的。实例属性是可变的,但不能添加额外的属性。
另一方面,有一些数据classes(根据我收集的)通过定义一些 dunders(等)来帮助 class 创建,并且被 PEP 557 描述为 "mutable namedtuples with defaults".
我知道他们的目的不同,事实上你可以 use both of them。
dataclass
装饰器不影响属性的存储或检索方式。内存消耗和属性访问时间将表现得就像 class 是在没有 dataclass
.
的情况下写入的一样
使用 __slots__
的 class 与不使用 class 的类似 class 相比,内存消耗更少,属性访问速度稍快(因为插槽描述符节省了一些字典查找) __slots__
,无论 class 是否使用 dataclass
。这是一个计时示例,显示 dataclass
不影响属性查找时间,而 __slots__
会:
>>> import timeit
>>> import dataclasses
>>> @dataclasses.dataclass
... class Foo:
... a: int
... b: int
...
>>> class Bar:
... def __init__(self, a, b):
... self.a = a
... self.b = b
...
>>> foo = Foo(1, 2)
>>> bar = Bar(1, 2)
>>> timeit.timeit('foo.a', globals=globals())
0.08070236118510365
>>> timeit.timeit('bar.a', globals=globals())
0.07813134230673313
>>> timeit.timeit('foo.a', globals=globals(), number=10000000)
0.5699363159947097
>>> timeit.timeit('bar.a', globals=globals(), number=10000000)
0.5526750679127872
>>> @dataclasses.dataclass
... class FooSlots:
... __slots__ = ['a', 'b']
... a: int
... b: int
...
>>> class BarSlots:
... __slots__ = ['a', 'b']
... def __init__(self, a, b):
... self.a = a
... self.b = b
...
>>> fooslots = FooSlots(1, 2)
>>> barslots = BarSlots(1, 2)
>>> timeit.timeit('fooslots.a', globals=globals(), number=10000000)
0.46022069035097957
>>> timeit.timeit('barslots.a', globals=globals(), number=10000000)
0.4669580361805856
Python 的 __slots__
用于减少实例的内存占用,这是通过在 "small fixed-sized array[s], much like a tuple or a list" 中存储变量来实现的。实例属性是可变的,但不能添加额外的属性。
另一方面,有一些数据classes(根据我收集的)通过定义一些 dunders(等)来帮助 class 创建,并且被 PEP 557 描述为 "mutable namedtuples with defaults".
我知道他们的目的不同,事实上你可以 use both of them。
dataclass
装饰器不影响属性的存储或检索方式。内存消耗和属性访问时间将表现得就像 class 是在没有 dataclass
.
使用 __slots__
的 class 与不使用 class 的类似 class 相比,内存消耗更少,属性访问速度稍快(因为插槽描述符节省了一些字典查找) __slots__
,无论 class 是否使用 dataclass
。这是一个计时示例,显示 dataclass
不影响属性查找时间,而 __slots__
会:
>>> import timeit
>>> import dataclasses
>>> @dataclasses.dataclass
... class Foo:
... a: int
... b: int
...
>>> class Bar:
... def __init__(self, a, b):
... self.a = a
... self.b = b
...
>>> foo = Foo(1, 2)
>>> bar = Bar(1, 2)
>>> timeit.timeit('foo.a', globals=globals())
0.08070236118510365
>>> timeit.timeit('bar.a', globals=globals())
0.07813134230673313
>>> timeit.timeit('foo.a', globals=globals(), number=10000000)
0.5699363159947097
>>> timeit.timeit('bar.a', globals=globals(), number=10000000)
0.5526750679127872
>>> @dataclasses.dataclass
... class FooSlots:
... __slots__ = ['a', 'b']
... a: int
... b: int
...
>>> class BarSlots:
... __slots__ = ['a', 'b']
... def __init__(self, a, b):
... self.a = a
... self.b = b
...
>>> fooslots = FooSlots(1, 2)
>>> barslots = BarSlots(1, 2)
>>> timeit.timeit('fooslots.a', globals=globals(), number=10000000)
0.46022069035097957
>>> timeit.timeit('barslots.a', globals=globals(), number=10000000)
0.4669580361805856