Комментарии 8
Код в разделе "Объединяем slots, dict и weakref" кажется не корректным.
Решение — объединить слоты с возможностью динамического добавления атрибутов, добавив в slots специальные поля dict и weakref.
1) Кажется, вы не допилили форматирование тут - должно было быть с двумя подчёркиваниями до и после каждого. Вместо этого редактор автоматически их проконвертил в жирный шрифт.
2) Сам пример кода не содержит использования ничего из __slots__
.
В остальном, да, примерно соответствует ожидаемому.
Работает ли это на том же уровне в других движках? Насколько я помню, PyPy старается соответствовать, у нас с ним проблем с __slots__
не было. А другие?
В главе "Объединяем slots, dict и weakref" сказано "Иногда хочется всего одновременно. Решение — объединить слоты с возможностью динамического добавления атрибутов, добавив в slots специальные поля dict и weakref.", но в коде этого нет.
Как я понимаю, ожидался такой код:
import weakref
class Resource:
__slots__ = ('name', '__dict__', '__weakref__')
def __init__(self, name):
self.name = name
def __repr__(self):
return f"<Resource {self.name}>"
res = Resource("CacheResource")
weak_res = weakref.ref(res)
print("До удаления:", weak_res())
del res
print("После удаления:", weak_res())
# До удаления: <Resource CacheResource>
# После удаления: None
Верно?)
Последний скрин не тот что планировался, он повторяет скрин по классическому примеру использования слабой ссылки)
Ох как прикольно. использовал словарь объектов в своем коде. Думаю о круто, сейчас за оптимизирую свой код!!! Добавил __slots_ в описание класса и вуаля, был размер объекта 56(кст. чего? байт?), а со __slots_ _ 232
Да и похоже не работает __slots_ 2025 году статью на свалку времен
все любят Python за его динамичность
Любить язык за то худшее, что в нем есть? Увольте
А теперь замерим, сколько памяти реально экономится
А корректно ли так замерять потребление памяти, учитывая, что ранее в этой же статье было сказано:
когда вы создаёте новый объект, Python делает две вещи:
Создаёт сам объект в памяти.
Создаёт отдельный dict, который тоже занимает место.
Ключевое слово – отдельный. Может быть, нужно тогда приплюсовывать размер dict к объектам, которые его используют?
Проверим такой код:
import sys
class WithoutSlots:
def __init__(self, a, b):
self.a = a
self.b = b
class WithSlots:
__slots__ = ('a', 'b')
def __init__(self, a, b):
self.a = a
self.b = b
class WithSlotsAndDict:
__slots__ = ('a', 'b', '__dict__')
def __init__(self, a, b):
self.a = a
self.b = b
obj1 = WithoutSlots(1, 2)
obj2 = WithSlots(1, 2)
obj3 = WithSlotsAndDict(1, 2)
print("Размер объекта без __slots__:", sys.getsizeof(obj1) + sys.getsizeof(obj1.__dict__))
print("Размер объекта с __slots__:", sys.getsizeof(obj2))
print("Размер объекта с __slots__ и __dict__:", sys.getsizeof(obj3) + sys.getsizeof(obj3.__dict__))
Выводит (версия Python 3.12):
Размер объекта без __slots__: 344
Размер объекта с __slots__: 48
Размер объекта с __slots__ и __dict__: 360
И получается немного другая картинка. Как минимум, становится ясно, что использование slots и dict одновременно (в статье сказано, что это, типа, компромисс между динамичностью и потреблением памяти) – худшая затея из всех. Если нужна динамичность – тогда просто стандартный dict, и не страдать фигнёй.
Как работают dict, slots и weakref в Python (и зачем это знать)