Слабые ссылки в питоне - PullRequest
40 голосов
/ 28 марта 2012

Я пытался понять, как работает Python-список слабых ссылок / словарь, и читал документацию для него, однако я не могу понять, как они работают и для чего их можно использовать.Может ли кто-нибудь дать мне базовый пример того, что они делают / объяснение того, как они работают?Было бы очень признательно.

(РЕДАКТИРОВАТЬ) Используя код Томаса, когда я заменяю obj на [1,2,3], он выдает:

Traceback (most recent call last):
File "C:/Users/nonya/Desktop/test.py", line 9, in <module>
r = weakref.ref(obj)
TypeError: cannot create weak reference to 'list' object

Ответы [ 4 ]

52 голосов
/ 28 марта 2012

Теория

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

Слабые ссылки позволяют создавать ссылки на объект, которые не увеличивают количество ссылок.

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

Вы бы использовали слабые ссылки для дорогих объектов или чтобы избежать кругассылки (хотя сборщик мусора обычно делает это самостоятельно).

Использование

Вот рабочий пример, демонстрирующий их использование:

import weakref
import gc

class MyObject(object):
    def my_method(self):
        print 'my_method was called!'

obj = MyObject()
r = weakref.ref(obj)

gc.collect()
assert r() is obj #r() allows you to access the object referenced: it's there.

obj = 1 #Let's change what obj references to
gc.collect()
assert r() is None #There is no object left: it was gc'ed.
23 голосов
/ 18 декабря 2014

Хочу только отметить, что weakref.ref не работает для встроенного списка, поскольку в списке __slots__ нет __weakref__. Например, следующий код определяет контейнер списка, который поддерживает слабый адрес.

import weakref

class weaklist(list):
    __slots__ = '__weakref__',

l = weaklist()
r = weakref.ref(l)
10 голосов
/ 28 марта 2012

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

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

Второй случай, вероятно, более распространен - ​​он подходит, когда вы держите, например, список объектов для уведомления, и вы не хотите, чтобы система уведомлений предотвращала сбор мусора.

0 голосов
/ 01 июня 2019

Вот пример сравнения dict и WeakValueDictionary:

class C: pass
ci=C()
print(ci)

wvd = weakref.WeakValueDictionary({'key' : ci})
print(dict(wvd), len(wvd)) #1
del ci
print(dict(wvd), len(wvd)) #0

ci2=C()
d=dict()
d['key']=ci2
print(d, len(d))
del ci2
print(d, len(d))

А вот и вывод:

<__main__.C object at 0x00000213775A1E10>
{'key': <__main__.C object at 0x00000213775A1E10>} 1
{} 0
{'key': <__main__.C object at 0x0000021306B0E588>} 1
{'key': <__main__.C object at 0x0000021306B0E588>} 1

Обратите внимание, как в первом случае один размы del ci фактический объект также будет удален из словаря wvd.

В случае обычного или обычного класса Python-словаря dict мы можем попытаться удалить объект, но он все равно будетпоказано.


Примечание: если мы используем del, мы не будем вызывать gc.collect() после этого, поскольку просто del эффективно удаляет объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...