Python的__slots__和数据类的比较(内存方式和访问时间方式)是什么

时间:2018-05-14 14:23:47

标签: python python-3.7 python-dataclasses

Python的.findall()用于减少实例的内存占用,这可以通过将变量存储在“小型固定大小的数组[s]中来实现,就像元组或列表一样”。实例属性是可变的,但您无法添加其他属性。

另一方面,有一些数据类(从我收集的内容)通过定义一些dunders(等)来帮助创建类,并且由PEP 557表征为“具有默认值的可变命名元组”。

我理解他们的目的不同,事实上你可以use both of them

1 个答案:

答案 0 :(得分:2)

dataclass装饰器不会影响属性的存储或检索方式。内存消耗和属性访问时间的行为就像没有dataclass编写类一样。

使用__slots__的类将比不使用__slots__的类似类具有更少的内存消耗和更快的属性访问(因为插槽描述符保存了一些dict查找),无论是否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