Правильный способ использовать слабые ссылки в Python
У меня есть два класса Parent и Child. В любой момент времени будет только один родительский объект, но может быть несколько дочерних объектов. Родитель должен будет хранить ссылку на дочерние объекты в словаре, проиндексированном по дочернему имени. Ребенку также нужна ссылка на Родителя, поскольку он может вызывать одну из функций Родителя.
Я знаю, что я должен использовать слабый рефрен здесь. У меня есть два способа сделать это:
Способ первый
class Child():
def __init__( self, parent, name ):
self.parent_ = weakref.proxy( parent )
self.name_ = name
class Parent():
def __init__( self ):
self.children = {}
def createChild( self, name ):
self.children[ name ] = Child( self, name )
Способ второй
class Child():
def __init__( self, parent, name ):
self.parent_ = parent
self.name_ = name
class Parent():
def __init__( self ):
self.children = {}
def createChild( self, name ):
self.children[ name ] = Child( weakref.proxy( self ), name )
- Есть ли разница в ч / б метод первый и второй?
- Каков наилучший способ достижения этой функциональности?
Редактировать: Когда Родитель умирает, Дети также должны умереть. Я не хочу, чтобы какой-либо дочерний объект существовал, если родительский объект не существует.
3 ответа
Вам действительно нужны слабые ссылки здесь? Если вы использовали свой метод один только с
self.parent = parent
ты достиг бы того, что собираешься делать. Слабая ссылка на parent позволила бы уничтожить родительский объект, если на него больше нет сильной ссылки, но в этом случае дети не смогут вызывать функции родителя, поскольку объект не будет существовать.
Методы 1 и 2 выглядят одинаково для меня.
р
В ответ на ваши вопросы:
- Методы 1 и 2 эквивалентны.
- В общем, звонить не нужно
weakref.proxy()
непосредственно. В этом случае вы можете использовать WeakValueDictionary, который является:
Класс сопоставления, который слабо ссылается на значения. Записи в словаре будут отброшены, если нет более строгой ссылки на значение.
Я думаю, что вы хотите, чтобы это было за пределами родительского класса (так как вы хотите, чтобы оно все еще было, если родитель удален), с ключами, идентифицирующими дочерние элементы, и значениями, предоставляющими родительский класс. Так что у вас будет что-то вроде этого:
registry = weakref.WeakValueDictionary()
class Child():
def __init__(self, parent, name):
self.parent = parent
self.name = name
class Parent():
def __init__(self):
pass
def createChild(self, name):
child = Child(self, name)
registry[child] = self
Кроме того, имена Child
а также Parent
здесь немного запутанно - условно они подразумевают, что Child
наследуется от Parent
(в этом случае вы можете просто вызвать метод родителя непосредственно для дочернего элемента и не требовать, чтобы "дочерний элемент" знал имя родителя). То, что у вас здесь есть, это отношения, а не отношения.
Ваши два подхода эквивалентны, они дают одинаковый результат.
Слабые ссылки используются, когда вы хотите, чтобы упомянутые объекты собирались мусором, даже если ваши (слабые) ссылки все еще существуют. В вашем случае ваш Parent
имеет регулярные ссылки на ваш Child
случаи, но дети имеют слабые ссылки на своих общих родителей. Это означает, что - в некоторых случаях - родитель будет собирать мусор, даже если есть дети, которые могут его использовать.
Я думаю, вы можете просто использовать регулярную, сильную ссылку здесь.