【问题标题】:What is the (memory-wise and access-time-wise) comparison of Python's __slots__ and dataclassesPython 的 __slots__ 和数据类的(内存方面和访问时间方面)比较是什么
【发布时间】:2018-10-24 06:06:13
【问题描述】:

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

另一方面,有一些数据类(根据我收集的信息)通过定义一些 dunders(等)来帮助创建类,并且 PEP 557 将其描述为“具有默认值的可变命名元组”。

我知道他们的目的是不同的,事实上你可以use both of them

【问题讨论】:

  • 目前尝试同时使用它们实际上并不能很好地工作 - 插槽描述符将与默认值或字段对象冲突。

标签: python python-3.7 python-dataclasses


【解决方案1】:

dataclass 装饰器不会影响属性的存储或检索方式。内存消耗和属性访问时间的行为与在没有dataclass 的情况下编写的类完全相同。

使用__slots__ 的类将比不使用__slots__ 的类似类具有更少的内存消耗和稍快的属性访问(因为槽描述符保存了一些dict 查找),无论任何一个类是否使用@987654325 @。这是一个计时示例,表明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

【讨论】:

  • 我觉得一次运行和 1000 万次查找的 9 毫秒差异并不显着,但似乎带有 __slots__ 的数据类的性能略高一些?我稍后会跟进一些内存测试...您是否可以通过不使用 __slots__ 的类上的构造函数来节省更多内存,而只需使用 setattr 插入值?
  • @ThisGuyCantEven:不。无论哪种方式,实例都会占用相同数量的内存。
  • 我以前见过这种模式,想知道为什么在构造函数上使用它,即使事先知道所有插槽,我认为它是为了节省 __init__ 分配,但不可否认,我知之甚少……
猜你喜欢
  • 1970-01-01
  • 2013-12-24
  • 1970-01-01
  • 2011-05-03
  • 2013-12-22
  • 2012-10-31
  • 1970-01-01
  • 2013-04-03
  • 1970-01-01
相关资源
最近更新 更多