Документация Python неофициальный перевод

weakref.md

227 строк · 22.3 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/2.7/library/weakref.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 8.11. [`weakref`](https://python-all.ru/2.7/library/weakref.html#module-weakref) – Слабые ссылки89Новое в версии 2.1.1011**Исходный код:** [Lib/weakref.py](https://python-all.ru/src/2.7/Lib/weakref.py)1213---1415Модуль [`weakref`](https://python-all.ru/2.7/library/weakref.html#module-weakref) позволяет программисту Python создавать *слабые ссылки* на объекты.1617В дальнейшем под термином *referent* понимается объект, на который указывает слабая ссылка.1819Слабая ссылка на объект не может сама по себе поддерживать его существование: когда единственными оставшимися ссылками на объект являются слабые ссылки, [сборщик мусора](https://python-all.ru/2.7/glossary.html#term-garbage-collection) может уничтожить этот объект и использовать его память для других целей. Основное применение слабых ссылок – реализация кэшей или отображений, содержащих крупные объекты, когда нежелательно, чтобы большой объект оставался в памяти только из-за того, что он присутствует в кэше или отображении.2021Например, если у вас есть несколько больших бинарных объектов-изображений, вы можете захотеть связать имя с каждым. Если вы используете словарь Python для отображения имён на изображения или изображений на имена, объекты-изображения будут оставаться живыми только потому, что они присутствуют как значения или ключи в словарях. Классы [`WeakKeyDictionary`](https://python-all.ru/2.7/library/weakref.html#weakref.WeakKeyDictionary) и [`WeakValueDictionary`](https://python-all.ru/2.7/library/weakref.html#weakref.WeakValueDictionary), предоставляемые модулем [`weakref`](https://python-all.ru/2.7/library/weakref.html#module-weakref), являются альтернативой: они используют слабые ссылки для построения отображений, которые не сохраняют объекты живыми только из-за их присутствия в объектах-отображениях. Если, например, объект-изображение является значением в [`WeakValueDictionary`](https://python-all.ru/2.7/library/weakref.html#weakref.WeakValueDictionary), то, когда последние оставшиеся ссылки на этот объект-изображение являются слабыми ссылками, хранящимися в слабых отображениях, сборщик мусора может переработать объект, и соответствующие записи в слабых отображениях просто удаляются.2223[`WeakKeyDictionary`](https://python-all.ru/2.7/library/weakref.html#weakref.WeakKeyDictionary) и [`WeakValueDictionary`](https://python-all.ru/2.7/library/weakref.html#weakref.WeakValueDictionary) используют слабые ссылки в своей реализации, устанавливая функции обратного вызова на слабые ссылки, которые уведомляют слабые словари, когда ключ или значение были изъяты сборщиком мусора. Большинству программ достаточно использовать один из этих типов слабых словарей – обычно нет необходимости создавать собственные слабые ссылки напрямую. Низкоуровневые механизмы, используемые реализациями слабых словарей, предоставляются модулем [`weakref`](https://python-all.ru/2.7/library/weakref.html#module-weakref) для расширенного использования.2425Не все объекты могут быть слабо ссылаемыми; объекты, которые могут, включают экземпляры классов, функции, написанные на Python (но не на C), методы (связанные и несвязанные), множества, неизменяемые множества, файловые объекты, [генератор](https://python-all.ru/2.7/glossary.html#term-generator)ы, объекты типов, объекты `DBcursor` из модуля [`bsddb`](https://python-all.ru/2.7/library/bsddb.html#module-bsddb), сокеты, массивы, дека, объекты регулярных выражений и объекты кода.2627Изменено в версии 2.4: Добавлена поддержка файлов, сокетов, массивов и шаблонов.2829Изменено в версии 2.7: Добавлена поддержка thread.lock, threading.Lock и объектов кода.3031Некоторые встроенные типы, такие как `list` и [`dict`](https://python-all.ru/2.7/library/stdtypes.html#dict), не поддерживают напрямую слабые ссылки, но могут добавить поддержку через наследование:3233```python34class Dict(dict):35    pass3637obj = Dict(red=1, green=2, blue=3)   # этот объект поддерживает слабые ссылки38```3940**Особенность реализации CPython:** Другие встроенные типы, такие как [`tuple`](https://python-all.ru/2.7/library/functions.html#tuple) и [`long`](https://python-all.ru/2.7/library/functions.html#long), не поддерживают слабые ссылки, даже если создать их подкласс.4142Расширяемые типы можно легко научить поддерживать слабые ссылки; см. [Поддержка слабых ссылок](https://python-all.ru/2.7/extending/newtypes.html#weakref-support).4344#### `class weakref.ref(object[, callback])`4546Возвращает слабую ссылку на *object*. Исходный объект можно получить, вызвав объект ссылки, если референт ещё жив; если референт больше не жив, вызов объекта ссылки приведёт к возврату [`None`](https://python-all.ru/2.7/library/constants.html#None). Если *колбэк* указан и не равен [`None`](https://python-all.ru/2.7/library/constants.html#None), и возвращённый объект weakref всё ещё жив, колбэк будет вызван, когда объект будет близок к финализации; объект слабой ссылки будет передан как единственный параметр колбэку; референт больше не будет доступен.4748Допускается создание нескольких слабых ссылок на один и тот же объект. Колбэки, зарегистрированные для каждой слабой ссылки, будут вызываться от самого недавно зарегистрированного колбэка до самого старого.4950Исключения, возбуждаемые колбэком, будут отмечены в стандартном потоке ошибок, но не могут быть распространены; они обрабатываются точно так же, как исключения, возбуждаемые методом [`__del__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__del__) объекта.5152Слабые ссылки [хэшируемы](https://python-all.ru/2.7/glossary.html#term-hashable), если *объект* хэшируем. Они сохраняют своё хэш-значение даже после удаления *объекта*. Если [`hash()`](https://python-all.ru/2.7/library/functions.html#hash) вызывается впервые только после удаления *объекта*, вызов вызовет [`TypeError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.TypeError).5354Слабые ссылки поддерживают проверку на равенство, но не на упорядочивание. Если референты ещё живы, две ссылки имеют то же отношение равенства, что и их референты (независимо от *колбэк*). Если любой из референтов был удалён, ссылки равны только в том случае, если объекты ссылок являются одним и тем же объектом.5556Изменено в версии 2.4: Теперь это тип, от которого можно наследовать, а не фабричная функция; он происходит от [`object`](https://python-all.ru/2.7/library/functions.html#object).5758#### `weakref.proxy(object[, callback])`5960Возвращает прокси для *объекта*, который использует слабую ссылку. Это позволяет использовать прокси в большинстве контекстов без необходимости явного разыменования, как в случае с объектами слабых ссылок. Возвращаемый объект будет иметь тип `ProxyType` или `CallableProxyType` в зависимости от того, является ли *объект* вызываемым. Прокси-объекты не являются [хешируемыми](https://python-all.ru/2.7/glossary.html#term-hashable) независимо от референта; это позволяет избежать ряда проблем, связанных с их принципиально изменчивой природой, и предотвращает их использование в качестве ключей словаря. *колбэк* – это тот же параметр с таким же именем, что и у функции [`ref()`](https://python-all.ru/2.7/library/weakref.html#weakref.ref).6162#### `weakref.getweakrefcount(object)`6364Возвращает количество слабых ссылок и прокси, которые ссылаются на *object*.6566#### `weakref.getweakrefs(object)`6768Возвращает список всех объектов слабых ссылок и прокси, которые ссылаются на *object*.6970#### `class weakref.WeakKeyDictionary([dict])`7172Класс отображения, который хранит слабые ссылки на ключи. Записи словаря будут удалены, когда на ключ больше не останется сильных ссылок. Это можно использовать для связывания дополнительных данных с объектом, принадлежащим другим частям приложения, без добавления атрибутов к этим объектам. Это особенно полезно для объектов, которые переопределяют доступ к атрибутам.7374> **Примечание**75>76> Предостережение: поскольку [`WeakKeyDictionary`](https://python-all.ru/2.7/library/weakref.html#weakref.WeakKeyDictionary) построен поверх словаря Python, его размер не должен изменяться при итерации по нему. Это может быть трудно гарантировать для [`WeakKeyDictionary`](https://python-all.ru/2.7/library/weakref.html#weakref.WeakKeyDictionary), поскольку действия, выполняемые программой во время итерации, могут привести к тому, что элементы словаря исчезнут «магическим образом» (как побочный эффект сборки мусора).7778Объекты [`WeakKeyDictionary`](https://python-all.ru/2.7/library/weakref.html#weakref.WeakKeyDictionary) имеют следующие дополнительные методы. Они открывают доступ к внутренним ссылкам напрямую. Ссылки не гарантированно «живы» на момент использования, поэтому результат вызова ссылок нужно проверять перед использованием. Это можно использовать, чтобы избежать создания ссылок, которые заставят сборщик мусора удерживать ключи дольше, чем необходимо.7980#### `WeakKeyDictionary.iterkeyrefs()`8182Возвращает итератор по слабым ссылкам на ключи.8384Новое в версии 2.5.8586#### `WeakKeyDictionary.keyrefs()`8788Возвращает список слабых ссылок на ключи.8990Новое в версии 2.5.9192#### `class weakref.WeakValueDictionary([dict])`9394Класс отображения, который хранит слабые ссылки на значения. Записи словаря будут удалены, когда на значение больше не будет сильных ссылок.9596> **Примечание**97>98> Предостережение: поскольку [`WeakValueDictionary`](https://python-all.ru/2.7/library/weakref.html#weakref.WeakValueDictionary) построен поверх словаря Python, его размер не должен изменяться при итерации по нему. Это может быть трудно гарантировать для [`WeakValueDictionary`](https://python-all.ru/2.7/library/weakref.html#weakref.WeakValueDictionary), поскольку действия, выполняемые программой во время итерации, могут привести к тому, что элементы словаря исчезнут «магическим образом» (как побочный эффект сборки мусора).99100Объекты [`WeakValueDictionary`](https://python-all.ru/2.7/library/weakref.html#weakref.WeakValueDictionary) имеют следующие дополнительные методы. Эти методы имеют те же проблемы, что и методы `iterkeyrefs()` и `keyrefs()` объектов [`WeakKeyDictionary`](https://python-all.ru/2.7/library/weakref.html#weakref.WeakKeyDictionary).101102#### `WeakValueDictionary.itervaluerefs()`103104Возвращает итератор по слабым ссылкам на значения.105106Новое в версии 2.5.107108#### `WeakValueDictionary.valuerefs()`109110Возвращает список слабых ссылок на значения.111112Новое в версии 2.5.113114#### `class weakref.WeakSet([elements])`115116Класс множества, который хранит слабые ссылки на свои элементы. Элемент будет удален, когда на него больше не останется сильных ссылок.117118Новое в версии 2.7.119120#### `weakref.ReferenceType`121122Объект типа для объектов слабых ссылок.123124#### `weakref.ProxyType`125126Объект типа для прокси-объектов, которые не являются вызываемыми.127128#### `weakref.CallableProxyType`129130Объект типа для прокси вызываемых объектов.131132#### `weakref.ProxyTypes`133134Последовательность, содержащая все объекты типа для прокси. Это упрощает проверку, является ли объект прокси, без необходимости называть оба типа прокси.135136#### `exception weakref.ReferenceError`137138Исключение, возникающее при использовании прокси-объекта, но базовый объект уже был собран. Это то же самое, что и стандартное исключение [`ReferenceError`](https://python-all.ru/2.7/library/weakref.html#weakref.ReferenceError).139140> **См. также**141>142> **[**PEP 205**](https://python-all.ru/2.7/library/weakref.html) – слабые ссылки**143>144> Предложение и обоснование этой возможности, включая ссылки на более ранние реализации и информацию о подобных возможностях в других языках.145146## 8.11.1. Объекты слабых ссылок147148Объекты слабых ссылок не имеют атрибутов или методов, но позволяют получить референт, если он ещё существует, вызвав объект слабой ссылки:149150```python151>>> import weakref152>>> class Object:153...     pass154...155>>> o = Object()156>>> r = weakref.ref(o)157>>> o2 = r()158>>> o is o2159True160```161162Если объект ссылки больше не существует, вызов объекта ссылки возвращает [`None`](https://python-all.ru/2.7/library/constants.html#None):163164```python165>>> del o, o2166>>> print r()167None168```169170Проверка того, что объект слабой ссылки всё ещё жив, должна выполняться с помощью выражения `ref() is not None`. Обычно код приложения, которому нужно использовать объект ссылки, должен следовать следующему шаблону:171172```python173# r – объект слабой ссылки174o = r()175if o is None:176    # объект был собран сборщиком мусора177    print "Object has been deallocated; can't frobnicate."178else:179    print "Object is still live!"180    o.do_something_useful()181```182183Использование отдельной проверки «живучести» создаёт состояния гонки в многопоточных приложениях; другой поток может привести к инвалидации слабой ссылки до того, как она будет вызвана; идиома, показанная выше, безопасна как в многопоточных, так и в однопоточных приложениях.184185Специализированные версии объектов [`ref`](https://python-all.ru/2.7/library/weakref.html#weakref.ref) можно создавать через наследование. Это используется в реализации [`WeakValueDictionary`](https://python-all.ru/2.7/library/weakref.html#weakref.WeakValueDictionary) для уменьшения накладных расходов памяти на каждую запись в отображении. Это может быть особенно полезно для связывания дополнительной информации со ссылкой, но также может использоваться для добавления дополнительной обработки при вызовах для получения объекта ссылки.186187Этот пример показывает, как подкласс [`ref`](https://python-all.ru/2.7/library/weakref.html#weakref.ref) можно использовать для хранения дополнительной информации об объекте и влиять на значение, возвращаемое при обращении к объекту ссылки:188189```python190import weakref191192class ExtendedRef(weakref.ref):193    def __init__(self, ob, callback=None, **annotations):194        super(ExtendedRef, self).__init__(ob, callback)195        self.__counter = 0196        for k, v in annotations.iteritems():197            setattr(self, k, v)198199    def __call__(self):200        """Возвращает пару, содержащую объект и количество201        вызовов ссылки.202        """203        ob = super(ExtendedRef, self).__call__()204        if ob is not None:205            self.__counter += 1206            ob = (ob, self.__counter)207        return ob208```209210## 8.11.2. Пример211212Этот простой пример показывает, как приложение может использовать идентификаторы объектов для получения объектов, которые оно уже видело. Идентификаторы объектов затем можно использовать в других структурах данных, не заставляя объекты оставаться живыми, но объекты всё ещё можно получить по идентификатору, если они живы.213214```python215import weakref216217_id2obj_dict = weakref.WeakValueDictionary()218219def remember(obj):220    oid = id(obj)221    _id2obj_dict[oid] = obj222    return oid223224def id2obj(oid):225    return _id2obj_dict[oid]226```227