Короткий ответ
weakref создаёт ссылку на объект, которая не увеличивает его счётчик ссылок и не мешает объекту быть собранным сборщиком мусора — полезна для кэшей и регистров наблюдателей, которые не должны продлевать жизнь объектов.
Как это работает подробнее
Обычная ссылка увеличивает refcount объекта, и пока она существует, объект не освобождается. weakref.ref(obj) (или WeakValueDictionary/WeakKeyDictionary) не увеличивает refcount — при обращении к ссылке на уже удалённый объект возвращается None, а в словаре элемент автоматически исчезает.
Пример кода
example-274.py
import weakref
class Resource:
def __init__(self, name):
self.name = name
r = Resource("conn-1")
weak_r = weakref.ref(r)
print(weak_r()) # <Resource object>, объект ещё жив
del r
print(weak_r()) # None - объект уже собран, так как не осталось сильных ссылокЧто использовать на практике
- Практика. Типичное применение — кэш объектов, где кэш не должен быть единственной причиной, по которой объект «живёт» дольше, чем реальный код (
WeakValueDictionary); или паттерн «наблюдатель», где подписчики не должны держаться в памяти только потому, что на них подписан внешний реестр.
Подводные камни
- Риски. Используют обычный словарь для кэша объектов и удивляются, что память не освобождается, хотя «видимых» внешних ссылок нет — на самом деле ссылка из кэша и есть причина; обращаются к слабой ссылке без проверки на
None.