5

Python でデリゲート パターンを使用すると循環参照が発生するかどうかを尋ねたいと思います。もしそうなら、オブジェクトとそのデリゲートが確実にガベージ コレクションされるように実装する最良の方法は何でしょうか?

Objective C では、デリゲートへの弱い参照を使用することで、上記の問題を回避しています。C++ では、デリゲートで delete を呼び出しません。Python の弱い参照モジュールへのリンクを見つけました: http://docs.python.org/library/weakref.html。このモジュールを使用してインスタンス変数を参照する弱い参照を作成するのがもっともらしいアプローチのようですが、よくわかりません。

私はこの質問をグーグルで検索しましたが、それに対する答えを見つけることができませんでした.の?また、質問する前にstackoverflowを検索しましたが、見つけた質問は循環インポートまたは一般的なデリゲートパターンのいずれかであり、Pythonおよび循環参照の問題に固有のものではありません。

返信ありがとうございます。

以下にリストされているのは、私の質問を説明するのに役立つおもちゃの例のコードです。この方法でコードを実装しましたが、動作しますが、最後にメモリがガベージ コレクションされるかどうかはわかりません。

class A(object):
    def __init__(self):
        self.delegate = None

        # Some other instance variables that keep track of state for performing some tasks.

    def doSomething(self):
        if self.delegate is not None:
            self.delegate.doSomething()
        else:
            print('Cannot perform task because delegate is not set.')

    # Other methods not shown.

class B(object):
    def __init__(self):
        self.a = A() # Need to keep object 'a' from garbage collected so as to preserve its state information.
        self.a.delegate = self  # Is this a circular reference? How to 'fix' it so that A and B will eventually be garbage collected?

    def doSomething(self):
        print('B doing something')

    # Other methods not shown.

編集

いくつかの返信を読んだ後、質問を明確にすることにしました。Pythonにはガベージコレクションがあることを理解しています。私が確信していなかったのは、循環参照オブジェクトでガベージ コレクションを実行するかどうかでした。私の心配は、Python のドキュメントからの次の一節から生じています。

CPython 実装の詳細: CPython は現在、循環的にリンクされたガベージの (オプションの) 遅延検出を伴う参照カウント スキームを使用しています。循環ガーベッジの収集の制御については、gc モジュールの資料を参照してください。他の実装では動作が異なり、CPython は変更される可能性があります。オブジェクトが到達不能になったときにオブジェクトの即時ファイナライズに依存しないでください (例: 常にファイルを閉じます)。

元の形式のパッセージはここにあります: http://docs.python.org/reference/datamodel.html太字の設定は私のものです。

次の投稿では、循環参照オブジェクトの問題と、それらのオブジェクトでのガベージ コレクションが妨げられる理由について、より明確に説明しています (少なくとも一般的な設定では): http://www.electricmonk.nl/log/2008/07/07 /python-destructor-and-garbage-collection-notes/ .

さらに、Python ユーザーが循環参照について心配する必要があるかどうかについての次の質問に対する Alex Martellli の回答に出くわしました: Python での循環参照について心配する必要がありますか? 彼の答えから、循環参照オブジェクトは最終的にガベージコレクションされますが、オーバーヘッドがあると思います。意味があるかどうかは、プログラムによって異なります。

さらに、彼は Python の weakref モジュールを使用すると述べましたが、その方法については明示的に述べませんでした。

したがって、いくつかの未解決の問題を明確にするために、次の質問を追加したいと思います。

  1. ドキュメントによると、循環参照オブジェクトのガベージコレクションは保証されていません。しかし、回答を見るとそうではないようです。それで、私はその箇所を誤解しましたか、それとも見逃した詳細がありますか?
  2. アレックスの返信と私の質問に記載されているように、弱い参照を使用すると、問題のオーバーヘッドを完全に回避できると思いますか?

返信ありがとうございます。

4

2 に答える 2

4

Pythonはすでにガベージコレクションを行っています。拡張機能としてCで独自のコンテナ型を作成する場合にのみ、特別なことを行う必要があります。

デモ:このプログラムを実行して、メモリ使用量が増加しないことを確認します。

class C(object):
    pass

def circular():
    for x in range(10**4):
        for y in range(10**4):
            a = C()
            b = C()
            a.x = b
            b.x = a

circular()

脚注:次の関数は何もしません。削除してください。

def setDelegate(self, delegate):
    self.delegate = delegate

を呼び出す代わりにx.setDelegate(y)、を使用できますx.delegate = y。Pythonでメンバーアクセスをオーバーロードできるため、メソッドを作成するメリットはありません。

于 2012-05-16T06:32:34.677 に答える
0

最後にガベージコレクションされないのはなぜですか? スクリプトが終了し、Python の実行が完了すると、メモリのセクション全体がガベージ コレクションと (最終的には) OS の回復用にマークされます。

これを実行時間の長いプログラムで実行している場合、A と B の両方が逆参照されると、メモリが再利用されます。

于 2012-05-16T06:37:07.647 に答える