Правильный способ использовать слабые ссылки в 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 )
  1. Есть ли разница в ч / б метод первый и второй?
  2. Каков наилучший способ достижения этой функциональности?

Редактировать: Когда Родитель умирает, Дети также должны умереть. Я не хочу, чтобы какой-либо дочерний объект существовал, если родительский объект не существует.

3 ответа

Вам действительно нужны слабые ссылки здесь? Если вы использовали свой метод один только с

self.parent = parent

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

Методы 1 и 2 выглядят одинаково для меня.

р

В ответ на ваши вопросы:

  1. Методы 1 и 2 эквивалентны.
  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 случаи, но дети имеют слабые ссылки на своих общих родителей. Это означает, что - в некоторых случаях - родитель будет собирать мусор, даже если есть дети, которые могут его использовать.

Я думаю, вы можете просто использовать регулярную, сильную ссылку здесь.

Другие вопросы по тегам