Что такое (по памяти и по времени доступа) сравнение Python __slots__ и классов данных - PullRequest
0 голосов
/ 14 мая 2018

Python __slots__ служит для уменьшения объема памяти экземпляров, и это достигается путем хранения переменных в «маленьком массиве фиксированного размера [s], очень похожем на кортеж или список».Атрибуты экземпляра являются изменяемыми, но вы не можете добавлять дополнительные атрибуты.

С другой стороны, существуют классы данных, которые (из того, что я собрал) помогают в создании классов, определяя некоторые из них (и т. Д.) И характеризуются PEP.557 как «изменяемые именованные кортежи со значениями по умолчанию».

Я понимаю, что их цели различны, и что вы на самом деле можете использовать оба из них .

1 Ответ

0 голосов
/ 19 мая 2018

Декоратор dataclass не влияет на то, как атрибуты сохраняются или извлекаются.Потребление памяти и время доступа к атрибутам будут вести себя точно так же, как если бы класс был написан без dataclass.

. Класс, который использует __slots__, будет иметь меньшее потребление памяти и немного более быстрый доступ к атрибутам (поскольку дескрипторы слотов экономят несколькоDICT поиска), чем аналогичный класс, который не использует __slots__, независимо от того, использует ли какой-либо класс 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
...