TL; DR Есть ли способ создать слабую ссылку, которая будет вызывать обратный вызов при наличии 1 сильной ссылки вместо 0?
Для тех, кто считает, что этопроблема XY, вот длинное объяснение:
У меня довольно сложная проблема, которую я пытаюсь решить с помощью своего кода.
Предположим, у нас есть экземпляр некоторого класса Foo идругой класс Bar, который ссылается на экземпляр в том виде, в котором он используется:
class Foo: # Can be anything
pass
class Bar:
"""I must hold the instance in order to do stuff"""
def __init__(self, inst):
self.inst = inst
foo_to_bar = {}
def get_bar(foo):
"""Creates Bar if one doesn't exist"""
return foo_to_bar.setdefault(foo, Bar(foo))
# We can either have
bar = get_foobar(Foo())
# Bar must hold a strong reference to foo
# Or
foo = Foo()
bar = get_foobar(foo)
bar2 = get_foobar(foo) # Same Bar
del bar
del bar2
bar3 = get_foobar(foo) # Same Bar
# In this case, as long as foo exists, we want the same bar to show up,
# therefore, foo must in some way hold a strong reference back to bar
Теперь вот сложная часть: вы можете решить эту проблему, используя циклическую ссылку, где foo
ссылки bar
и bar
ссылкиfoo
, но эй, а что тут интересного?Очистка займет больше времени, не будет работать, если Foo определит __slots__
и, как правило, будет плохим решением.
Есть ли способ, я могу создать отображение foo_to_bar
, которое очищает одиночный ссылка на foo
и bar
?По сути:
import weakref
foo_to_bar = weakref.WeakKeyDictionary()
# If bar is referenced only once (as the dict value) and foo is
# referenced only once (from bar.inst) their mapping will be cleared out
Таким образом, он может отлично работать, поскольку наличие foo
вне функции гарантирует, что bar
все еще там (мне может потребоваться __slots__
на Foo
для поддержки __weakref__
) и наличие bar
вне функции приводит к тому, что foo
все еще остается там (из-за сильного задания в Bar
).
WeakKeyDictionary
не работает, поскольку {weakref.ref(inst): bar.inst}
приведет к циклическому обращению.
В качестве альтернативы, есть ли способ подключиться к механизму подсчета ссылок (для очистки, когда оба объекта получают по 1 ссылке каждый) без значительных накладных расходов?