Spec-Zone.ru › Python 2.7

weakref — Слабые ссылки

Новое в версии 2.1.

Исходный код: Lib/weakref.py

Модуль weakref позволяет программисту Python создавать слабые ссылки на объекты.

В дальнейшем термин ссылочный объект означает объект, на который ссылается слабая ссылка.

Слабая ссылка на объект недостаточна для поддержания жизни объекта: когда единственными оставшимися ссылками на целевой объект являются слабые ссылки, сборщик мусора свободен уничтожить целевой объект и повторно использовать его память для чего-то другого. Основное применение слабых ссылок — реализация кэшей или отображений, содержащих большие объекты, где желательно, чтобы большой объект не сохранялся в живых только потому, что он появляется в кэше или отображении.

Например, если у вас есть несколько больших двоичных объектов изображений, вы можете захотеть связать имя с каждым из них. Если вы использовали словарь Python для сопоставления имён с изображениями или изображений с именами, объекты изображений оставались бы живыми только потому, что они появлялись в качестве значений или ключей в словарях. Классы WeakKeyDictionary и WeakValueDictionary, предоставленные модулем weakref, представляют собой альтернативу, используя слабые ссылки для построения отображений, которые не сохраняют объекты живыми только потому, что они появляются в объектах отображения. Если, например, объект изображения является значением в WeakValueDictionary, то когда последние оставшиеся ссылки на этот объект изображения — это слабые ссылки, удерживаемые слабыми отображениями, сборщик мусора может восстановить объект, а соответствующие записи в слабых отображениях просто удаляются.

WeakKeyDictionary и WeakValueDictionary используют слабые ссылки в своей реализации, настраивая функции обратного вызова на слабых ссылках, которые уведомляют слабые словари, когда ключ или значение были восстановлены сборщиком мусора. Большинству программ должно хватить использования одного из этих типов словарей со слабыми ссылками — обычно нет необходимости создавать свои слабые ссылки напрямую. Низкоуровневая машина, используемая реализациями словарей со слабыми ссылками, предоставляется модулем weakref для использования в продвинутых случаях.

Не все объекты могут быть слабо ссылаемыми; к таким объектам относятся экземпляры классов, функции, написанные на Python (но не на C), методы (связанные и несвязанные), множества, неизменяемые множества, файлы, генераторы, типы объектов, DBcursor объекты из модуля bsddb, сокеты, массивы, деки, объекты шаблонов регулярных выражений и объекты кода.

Изменено в версии 2.4: Добавлена поддержка файлов, сокетов, массивов и шаблонов.

Изменено в версии 2.7: Добавлена поддержка thread.lock, threading.Lock и объектов кода.

Некоторые встроенные типы, такие как list и dict, не поддерживают слабые ссылки напрямую, но могут добавить поддержку посредством наследования:

class Dict(dict):
    pass

obj = Dict(red=1, green=2, blue=3)   # this object is weak referenceable

Деталь реализации CPython: Другие встроенные типы, такие как tuple и long, не поддерживают слабые ссылки даже при наследовании.

Типы расширений легко могут быть сделаны для поддержки слабых ссылок; см. Поддержка слабых ссылок.

class weakref.ref(object[, callback])

Возвращает слабую ссылку на object. Исходный объект можно получить, вызвав объект ссылки, если целевой объект всё ещё жив; если целевой объект больше не жив, вызов объекта ссылки вызовет None. Если callback предоставлен и не None, а возвращаемый объект weakref всё ещё жив, функция обратного вызова будет вызвана, когда объект будет окончательно завершён; объект слабой ссылки будет передан в качестве единственного параметра в функцию обратного вызова; целевой объект больше не будет доступен.

Допускается создание многих слабых ссылок на один и тот же объект. Функции обратного вызова, зарегистрированные для каждой слабой ссылки, будут вызваны от самой недавно зарегистрированной функции обратного вызова к самой старой зарегистрированной функции обратного вызова.

Исключения, поднятые функцией обратного вызова, будут отображены в стандартном выводе ошибок, но не могут быть перехвачены; они обрабатываются точно так же, как исключения, поднятые из метода __del__() объекта.

Слабые ссылки являются хешируемыми, если object хешируем. Они сохранят своё значение хеша даже после удаления object. Если hash() вызывается в первый раз только после удаления object, вызов поднимет TypeError.

Слабые ссылки поддерживают проверки на равенство, но не порядок. Если целевые объекты всё ещё живы, две ссылки имеют ту же связь равенства, что и их целевые объекты (независимо от callback). Если один из целевых объектов был удалён, ссылки равны только если объекты ссылок являются одним и тем же объектом.

Изменено в версии 2.4: Теперь это подклассируемый тип, а не функция-фабрика; он наследуется от object.

weakref.proxy(object[, callback])

Возвращает прокси к object, который использует слабую ссылку. Это поддерживает использование прокси в большинстве контекстов вместо необходимости явного разыменования, используемого с объектами слабых ссылок. Возвращаемый объект будет иметь тип либо ProxyType либо CallableProxyType, в зависимости от того, является ли object вызываемым. Объекты прокси не хешируемы, независимо от целевого объекта; это избегает ряда проблем, связанных с их фундаментальной изменчивой природой и предотвращает их использование в качестве ключей словаря. callback такой же, как параметр с тем же именем в функции ref().

weakref.getweakrefcount(object)

Возвращает количество слабых ссылок и прокси, которые ссылаются на object.

weakref.getweakrefs(object)

Возвращает список всех объектов слабых ссылок и прокси, которые ссылаются на object.

class weakref.WeakKeyDictionary([dict])

Класс отображения, который слабо ссылается на ключи. Записи в словаре будут удалены, когда больше нет сильной ссылки на ключ. Это можно использовать для сопоставления дополнительной информации с объектом, принадлежащим другим частям приложения, без добавления атрибутов к этим объектам. Это особенно полезно для объектов, которые переопределяют доступ к атрибутам.

Примечание

Осторожно: так как WeakKeyDictionary построен на основе словаря Python, его размер не должен меняться во время итерации по нему. Это может быть сложно гарантировать для WeakKeyDictionary, так как действия, выполняемые программой во время итерации, могут привести к тому, что элементы в словаре исчезнут «магически» (как побочный эффект сборки мусора).

WeakKeyDictionary объекты имеют следующие дополнительные методы. Они напрямую предоставляют доступ к внутренним ссылкам. Не гарантируется, что ссылки будут «живыми» в момент использования, поэтому результат вызова ссылок нужно проверять перед использованием. Это можно использовать для предотвращения создания ссылок, которые заставят сборщик мусора сохранять ключи дольше, чем необходимо.

WeakKeyDictionary.iterkeyrefs()

Возвращает итерируемый объект слабых ссылок на ключи.

Новое в версии 2.5.

WeakKeyDictionary.keyrefs()

Возвращает список слабых ссылок на ключи.

Новое в версии 2.5.

class weakref.WeakValueDictionary([dict])

Класс отображения, который слабо ссылается на значения. Элементы в словаре будут удалены, когда больше не будет сильных ссылок на значение.

Примечание

Предупреждение: поскольку WeakValueDictionary построен на основе словаря Python, его размер не должен меняться во время итерирования по нему. Это может быть сложно обеспечить для WeakValueDictionary, так как действия, выполняемые программой во время итерации, могут привести к исчезновению элементов в словаре «волшебным» образом (в качестве побочного эффекта сборки мусора).

WeakValueDictionary объекты имеют следующие дополнительные методы. Эти методы имеют те же проблемы, что и методы iterkeyrefs() и keyrefs() объектов WeakKeyDictionary.

WeakValueDictionary.itervaluerefs()

Возвращает итерируемый объект слабых ссылок на значения.

Введено в версии 2.5.

WeakValueDictionary.valuerefs()

Возвращает список слабых ссылок на значения.

Введено в версии 2.5.

class weakref.WeakSet([elements])

Класс множества, который хранит слабые ссылки на свои элементы. Элемент будет удален, когда больше не будет сильных ссылок на него.

Введено в версии 2.7.

weakref.ReferenceType

Объект типа для слабых ссылок.

weakref.ProxyType

Объект типа для прокси-объектов, которые не являются вызываемыми.

weakref.CallableProxyType

Объект типа для прокси вызываемых объектов.

weakref.ProxyTypes

Последовательность, содержащая все объекты типов для прокси. Это может упростить проверку, является ли объект прокси, не завися от именования обоих типов прокси.

exception weakref.ReferenceError

Исключение, возникающее при использовании прокси-объекта, но лежащий в его основе объект был собран. Это то же самое, что и стандартное исключение ReferenceError.

См. также

PEP 205 - Слабые ссылки

Предложение и обоснование этой функции, включая ссылки на предыдущие реализации и информацию о похожих функциях в других языках.

1. Объекты слабых ссылок

Объекты слабых ссылок не имеют атрибутов или методов, но позволяют получить ссылку на целевой объект, если он существует, вызвав его:

>>> import weakref
>>> class Object:
...     pass
...
>>> o = Object()
>>> r = weakref.ref(o)
>>> o2 = r()
>>> o is o2
True

Если целевой объект больше не существует, вызов объекта ссылки возвращает None:

>>> del o, o2
>>> print r()
None

Проверка того, что объект слабой ссылки все еще жив, должна выполняться с помощью выражения ref() is not None. Обычно код приложения, которому необходимо использовать объект ссылки, должен следовать этому шаблону:

# r is a weak reference object
o = r()
if o is None:
    # referent has been garbage collected
    print "Object has been deallocated; can't frobnicate."
else:
    print "Object is still live!"
    o.do_something_useful()

Использование отдельной проверки «жизнеспособности» создаёт гонки в многопоточных приложениях; другой поток может привести к тому, что слабая ссылка станет недействительной до того, как слабая ссылка будет вызвана; показанный выше идиом безопасен как в многопоточных, так и в однопоточных приложениях.

Специализированные версии объектов ref могут быть созданы путём наследования. Это используется в реализации WeakValueDictionary, чтобы уменьшить накладные расходы памяти для каждой записи в отображении. Это может быть наиболее полезно для ассоциации дополнительной информации с ссылкой, но также может быть использовано для вставки дополнительной обработки при вызовах получения целевого объекта.

Этот пример показывает, как подкласс ref может быть использован для хранения дополнительной информации об объекте и влияния на значение, возвращаемое при обращении к целевому объекту:

import weakref

class ExtendedRef(weakref.ref):
    def __init__(self, ob, callback=None, **annotations):
        super(ExtendedRef, self).__init__(ob, callback)
        self.__counter = 0
        for k, v in annotations.iteritems():
            setattr(self, k, v)

    def __call__(self):
        """Return a pair containing the referent and the number of
        times the reference has been called.
        """
        ob = super(ExtendedRef, self).__call__()
        if ob is not None:
            self.__counter += 1
            ob = (ob, self.__counter)
        return ob

2. Пример

Этот простой пример показывает, как приложение может использовать идентификаторы объектов для получения объектов, которые оно видело ранее. Идентификаторы объектов затем могут быть использованы в других структурах данных без принудительного сохранения объектов, но объекты по-прежнему могут быть получены по идентификатору, если они существуют.

import weakref

_id2obj_dict = weakref.WeakValueDictionary()

def remember(obj):
    oid = id(obj)
    _id2obj_dict[oid] = obj
    return oid

def id2obj(oid):
    return _id2obj_dict[oid]

© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/2.7/library/weakref.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API