クラスのインスタンスが相互に親 <-> 子参照を持つコードがいくつかあります。たとえば、次のようになります。
class Node:
def __init__(self):
self.parent = None
self.children = {}
def AddChild(self, name, child):
child.parent = self
self.children[name] = child
def Run():
root, c1, c2 = Node(), Node(), Node()
root.AddChild('first', c1)
root.AddChild('second', c2)
Run()
これにより、のような循環参照が作成され、Run() の完了後に解放されないと思いますよね?. では、どうすれば解放されるのでしょうか。、または-のようなことができると思いますが、いつそれを行うべきかわからない場合はどうすればよいですか?root
c1
c2
root.children.clear()
self.parent = None
これはweakrefモジュールを使用する適切な時期ですか? 正確には、何を弱参照化しますか? 属性parent
?属性children
?オブジェクト全体?上記のすべて?WeakKeyDictionary と weakref.proxy についての話が見られますが、この場合、それらをどのように使用する必要があるかは明確ではありません。
これは Python 2.4 でもあります (アップグレードできません)。
更新: 例とまとめ
どのオブジェクトを弱参照化するかは、どのオブジェクトが他のオブジェクトなしで存続できるか、およびどのオブジェクトが相互に依存しているかによって異なります。寿命が最も長いオブジェクトには、寿命が短いオブジェクトへの弱参照が含まれている必要があります。同様に、weakref を依存関係に作成するべきではありません。作成すると、依存関係がまだ必要であるにもかかわらず、黙って消えてしまう可能性があります。
たとえば、ツリー構造 があり、root
子があり、子がなくkids
ても存在できる場合、オブジェクトはその にweakrefsを使用する必要があります。これは、子オブジェクトが親オブジェクトの存在に依存する場合にも当てはまります。以下では、子オブジェクトはその深さを計算するために親を必要とするため、 の強力な参照です。ただし、属性のメンバーはオプションであるため、循環参照を防ぐために弱い参照が使用されます。root
kids
parent
kids
class Node:
def __init__(self):
self.parent = None
self.kids = weakref.WeakValueDictionary()
def GetDepth(self):
root, depth = self, 0
while root:
depth += 1
root = root.parent
return depth
root = Node()
root.kids['one'] = Node()
root.kids['two'] = Node()
関係をひっくり返すために、以下のようなものがあります。ここで、Facade
クラスはSubsystem
機能するためにインスタンスを必要とするため、必要なサブシステムへの強力な参照を使用します。 Subsystem
ただし、s が機能する必要はありませんFacade
。 s は、互いのアクションについて sSubsystem
に通知する方法を提供するだけです。Facade
class Facade:
def __init__(self, subsystem):
self.subsystem = subsystem
subsystem.Register(self)
class Subsystem:
def __init__(self):
self.notify = []
def Register(self, who):
self.notify.append(weakref.proxy(who))
sub = Subsystem()
cli = Facade(sub)