New We are sorting MAX channels into categories and territories. Read the news

WeakKeyDictionary: как хранить данные «рядом с объектом» без прямой записи в атрибуты



Классический паттерн: хочется прикрепить доп. данные к объекту — делаешь obj._cache = .... Но у этого три проблемы:

— не работает для built-in типов и slotted классов
— имена атрибутов могут конфликтовать с другим кодом
— атрибуты вылезают в vars() и других местах где не ждёшь


🔑 Решение — WeakKeyDictionary

from weakref import WeakKeyDictionary
import ast

used_names_cache: WeakKeyDictionary[ast.Module, set[str]] = WeakKeyDictionary()

def all_used_names(module: ast.Module) -> set[str]:
try:
return used_names_cache[module]
except KeyError:
pass

names = set()
# ... заполняем set
used_names_cache[module] = names
return names

Данные живут «здесь», а не на объекте. Производительность O(1) как у обычного атрибута.

Главное преимущество: как только объект перестаёт существовать в остальном коде — запись в словаре тоже удаляется автоматически. Нет утечек памяти.


⚠️ Почему не functools.cache?

@cache
def all_used_names(module): ...

functools.cache хранит сильные ссылки на аргументы. Даже если module больше нигде не используется — кэш держит его живым и не даёт GC освободить память.


📋 Два условия для объекта

Объект должен быть hashable — выполняется по умолчанию если не переопределён __eq__ без __hash__.

Объект должен поддерживать weak reference — большинство user-defined классов поддерживают. Для slotted классов нужно явно добавить:

class Train:
__slots__ = ("__weakref__", "wheels", "engine")
Views: 117
Open in MAX Report an inaccuracy

Report an inaccuracy

Describe what needs fixing. If you have a source, add a link.

You are leaving datool.ru

The link leads to an external website. datool.ru is not responsible for its content — check the address before entering passwords or payment details.

Redirecting in 10 s

Go