Как стать автором
Поиск
Написать публикацию
Обновить

Комментарии 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 делает две вещи:

  1. Создаёт сам объект в памяти.

  2. Создаёт отдельный 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, и не страдать фигнёй.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий