2012-03-20 6 views
2

私が理解しているところから、Python 3は、少なくとも1つの非弱参照がオブジェクトを指している限り、オブジェクトのメモリが解放されないことを保証するものではありません。弱参照はオブジェクトを指していませんが、weakrefはNoneに評価できませんか?

この言語は弱い参照について他の保証を行っていますか?特に、何らかのオブジェクトを指し示す弱参照wrを作成したとします。後で、そのオブジェクトに対する非弱参照がすべて破棄されたとします。その時点でwrがNoneに評価されるか、それともしばらくの間元のオブジェクトに評価されることが保証されていますか?

言語保証以外に、weakrefに関する興味深い実装動作はありますか?

+1

この動作の正確なニュアンスに依存するトリッキーなコードを書くつもりはないと思いますが、私は個人的に 'weakref' FWIWを必要としませんでした。 –

+0

私はPyQtでweakkeydictionaryとweakvaluedictionaryを使用して、ウィジェットをガベージコレクションによって破壊されないようにしています。しかし...私は決してその妥当性に頼ることもありません。非弱点がゼロに達する点を超えて、弱点が有効なままであることを期待するべきではありません。 – jdi

+0

@KarlKnechtel:私は保証されていないものに応じて避けたい。実装固有のものではなく、言語によって保証されていれば、ニュアンスに頼っても構いません。 – max

答えて

1

weakrefは、有効なオブジェクト(PythonのPOVから)またはなしを提供します。オブジェクトが実際に割り当て解除されると(weakrefがNoneになる)、他のライブオブジェクトからのオブジェクトへの非弱参照はできません。 CPythonでの参照カウント動作は保証されていません。

+1

ありがとう!あなたのコメントは、オブジェクトが実際に割り当て解除されるまで、weakrefがNoneに評価されないことを意味しますか?そのような保証が存在する場合、1つの弱点がNoneに評価された場合、それらのすべてを実行することも意味します。 – max

+0

weakrefsを反転させるコードは、割り当て解除の一部として実行されます。 weakrefsは一緒にリンクされ、オブジェクトにリンクされます。しかし、これは実装の詳細かもしれません - オブジェクトが割り当て解除される前に弱点が決してNoneにならないことを保証したくありません。特に、割り当て解除は言語標準の概念ではありません。オブジェクトが到達不能かどうか。最も灰色の領域はおそらく、weakrefをたどって到達不能なオブジェクトを回復することが可能であるかどうかです。私はそれが起こり得ないと言いたくはありません。 –

+0

なぜこれは灰色の領域ですか?可能なだけではないようですが、最後の強い参照がなくなってからweakrefを有効にしておけば、確実に起こります。その時点で強力な参照を作成していれば、私はオブジェクトを復活させただけで、私は持っていません(つまり、Pythonは今それを破壊しないかもしれません)。何か不足していますか?私は、Pythonがweakrefを強力な参照に割り当てようとする試みをキャッチして、割り当ての前にweakrefをNoneに更新すると思います。しかし、そのような行動は、強い参照の有無を確認することが決して緊急ではないという考え方に反しているように思えます。 – max

1

弱参照オブジェクトは、GCが起動した場合にのみ破壊されます。これは非決定論的なので、すべての強力な参照が破棄されるとすぐに破棄されるという保証はありません。 docsから

...参照先にのみ、残りの参照が弱い 参照されたときに、ガベージコレクションが指示対象を破壊し、 は何か他のもののためにそのメモリを再利用して自由です。

操作句は「指示対象を自由に破壊することができます」 - すぐには発生しない可能性があります。

+0

オブジェクトの破壊が最初に起こり、確定的である可能性があると私は考えました。メモリは後でGCによって解放されますが、これは確定的ではありません。しかし、今私はそれについて考えている、彼らは同時に実行されていない場合変なことだろう - インタープリターがオブジェクトが破壊されていることをすでに知っている場合、なぜメモリを解放してください。 – max

1

いいえ、Pythonは、オブジェクトが実際に収集された時点を保証せず、weakrefはNoneを返します。すぐに発生する可能性があります(また、参照カウントと循環参照ガベージコレクタを使用するCPythonによくありますが、refcountingを使用しない他のPython実装ではあまり頻繁ではありません)。理由 - CPythonを使用しない場合(またはrefcountingを使用しないCPythonのバージョンを使用する場合)、またはrefcountingを使用する場合、オブジェクトが参照サイクルに参加する場合。

+0

これは自動的にあなたの答えhttp://stackoverflow.com/a/9796689/336527で、正しい?そこでは、最後の強力な参照が削除された後、 '__del__'が任意に呼び出されることはないと説明します。 weakrefは '__del__'が完了するまで' None'を返すことはできません( '__del__'がまだオブジェクトを復活させる可能性があるからです)。 – max

0

コヒーレントにリリースされているすべての弱い参照は保証されていないようです(Guidoの投稿に従って)。あなたができることの1つは、別の方法で新しい弱参照を生成するすべての場所で単一の弱参照を使用することです(単一の参照はそれを使用しているすべての人に同じに見える必要があるためです)。

ここでは、さまざまな参照への参照のための素敵なコールバックの仕組みが失われますが、weakref.refをサブクラス化して何らかの登録スキームを追加することで回復できます。 weakrefの単一のインスタンスを見つける方法も必要です。参照するインスタンスと一緒にパッケージ化し、getまたはcreate-helperメソッドを作成します(スレッドの安全性の問題に注意して、ロックを必要としない場合はデフォルトでgetattrを使用してください)。あるいは、シングルトンでそれらを見つけることもできます(最初のメソッドを使用してください...)。

弱弱でのコヒーレントな解読は、普通のメモ作成スキームのために保証する必要があるようですが、単一の弱参照を使用することは、通訳者の弱参照スキームを必要な保証で再実装する犠牲を払っても機能するはずです。

実際には.__weakref__という属性を使用することができます。ここでweakrefsはインタープリタ内のインスタンスに表示され、ヘルパー関数のメソッドを使用します。

+0

weakrefの「無効化」のタイミングが懸念されるのはなぜですか?同時に起こることが保証されていないことがわかっている限り、私たちはそれに依存しないので、うまくいきます。あなたはそれについてどのような状況を思い出して、メモ作成の狂気につながるでしょうか? – max

+0

2つの異なる場所がmemoizationキャッシュを共有し、それぞれがweakrefを持ち、weakrefが反転するたびに新しいキャッシュを再構築/開始することを知っているとします。両方が同時にNoneを返すという保証がなければ、異なるキャッシュを使用することができます。私はこれがちょっと工夫されており、実際にはcPythonでは決して見られないだろうと認めますが、これは、弱い1つのリファレンスがNoneを返す場合に、すべてを返すという期待を強制する方法と考えていました。 –

+0

(ユニークな)キャッシュマネージャオブジェクトは、強力な参照にリンクされていませんし、そのマネージャからのみ、(単体の)weakrefが実際のデータ位置を指していませんか?たぶん私は複数のweakrefデザインの良い理由を見逃しています、ごめんなさい - 私はちょうどこの事を学んでいます。 – max

関連する問題