Работа с циклическими ссылками, как это, вероятно, поможет вам, но, без сомнения, я все равно попытаюсь ответить на ваш вопрос.
Словарь Python хранит ссылки как на его ключи, так и на его значения.A WeakKeyDictionary хранит слабые ссылки на его ключи, но strong ссылки на его значения.Итак, в вашем первом примере, если вы установите w[m] = m
, словарь w
имеет слабую ссылку на m
в качестве ключа и сильную ссылку на m
в качестве значения.
Модуль Python слабой ссылки такжеимеет WeakValueDictionary, который имеет сильные ссылки на свои ключи и слабые ссылки на его значения, но это не решит вашу проблему.
Что вам действительно нужно, так это словарь, который имеет слабые ссылки как на свои ключи, так и на значения.Следующий код явно делает каждое значение в словаре слабой ссылкой:
import weakref
import gc
class M():
pass
class Other():
pass
m = M()
w = weakref.WeakKeyDictionary()
w[m] = weakref.ref(m)
print len(w.keys()) # prints 1
del m
print len(w.keys()) # prints 0
m = M()
o = Other()
o.strong_ref = m
w[m] = weakref.ref(o)
print len(w.keys()) # prints 1
del m
print len(w.keys()) # prints 1
del o
print len(w.keys()) # prints 0
Вы можете сделать значение слабой ссылкой автоматически, подклассифицировав WeakKeyDictionary.Обратите внимание, однако, что это не ведет себя как настоящий WeakValueDictionary, потому что он не имеет обратного вызова для уведомления словаря, когда значение было удалено.
class MyWeakKeyValueDictionary(weakref.WeakKeyDictionary):
def __init__(self):
weakref.WeakKeyDictionary.__init__(self)
def __setitem__(self, key, value):
weakref.WeakKeyDictionary.__setitem__(self, key, weakref.ref(value))
w2 = MyWeakKeyValueDictionary()
m = M()
w2[m] = m
print len(w2.keys()) # prints 1
del m
print len(w2.keys()) # prints 0
m = M()
o = Other()
o.strong_ref = m
w2[m] = o
print len(w2.keys()) # prints 1
del m
print len(w2.keys()) # prints 1
del o
print len(w2.keys()) # prints 0
В конце концов,однако, я боюсь, что попытка справиться с циклическими ссылками может вызвать больше проблем, чем оно того стоит.