2009-07-10 9 views
7

私はPythonでクラスを書く方法について考えてきました。具体的には、コンストラクターの実装方法とオブジェクトの破棄方法について説明します。オブジェクトのクリーンアップを行うためにCPythonの参照カウントに頼るのは嫌です。これは、基本的に、オブジェクトのライフタイムを管理するためにステートメントを使用する必要があり、明示的なclose/disposeメソッドが必要であることを示しています(このメソッドは、オブジェクトがコンテキストマネージャでもある場合__exit__から呼び出すことができます)。__del__でオブジェクトのクローズ/破棄を行うことは本当に問題ありませんか?

class Foo(object): 
    def __init__(self): 
     pass 
    def close(self): 
     pass 

、私のすべてのオブジェクトが、このように動作し、すべての私のコードは、ステートメントまたはclose()(またはdispose())への明示的な呼び出しで使用する場合、私は本当に私が__del__で任意のコードを配置する必要性が表示されません。私たちのオブジェクトを処分するのに本当に__del__を使うべきですか?

+2

私はオブジェクトのクリーンアップを行うためにCPythonの参照カウントに頼りたくありません。なぜ地球上ではないのですか?オブジェクト参照カウントで何が問題になっていますか? –

+0

@ S.Lott、JythonやIronPythonなどのより高度なガベージコレクションを使用する環境にコードを移動すると、リファレンスカウントは存在しません。また、ある日CPython(Unladen Swallowなど)が蹴ったり叫んだりするとどうなるでしょうか? 21世紀に入っても?私は再利用可能な移植可能なライブラリ(使い捨て、スロー・アウェイ、スクリプト、マイナー・モジュールとは対照的に)でRCに「依存しない」というOPに同意します。 –

+0

@ S.Lott:Alexはあなたの質問に既に答えました。参照カウントに依存したくないもう一つの理由は、JITがPyPyプロジェクトから出てくることです。その背後にいる人々は、CPythonに比べて部分的なスピードアップを実現できると楽観的に思えます。 – Arlaharen

答えて

13

短い答え:いいえ。

長い答え:__del__を使用するには、呼び出されることを保証しませんだ主な理由は、注意が必要です。つまり、絶対にやる必要のあることはできません。つまり、__del__は、プロセスが終了したときにクリーンアップされるリソースをクリーンアップするなど、遅かれ早かれ起こるクリーンアップのためにのみ使用することができるため、__del__が呼び出されなくても問題ありません。もちろん、これはPythonが一般的にあなたと同じことです。だからちょっと__del__は役に立たない。

また、Pythonのガベージコレクションでは、__del__が呼び出され、Pythonのガベージコレクションを待たずに済みます。つまり、とにかく__del__は使用できません。

したがって、__del__は使用しないでください。代わりに__enter__/__exit__を使用してください。FYI

:ここでは、デストラクタが呼び出されませんでした非円形の状況の例である:

class A(object): 
    def __init__(self): 
     print('Constructing A') 

    def __del__(self): 
     print('Destructing A') 

class B(object): 
    a = A() 

OK、それはクラス属性です。明らかにそれは特殊なケースです。しかし、それはちょうど__del__が呼び出されることを確認することが簡単ではないことを示すために行く。 __del__が呼び出されていないより多くの非円形の状況を見てきたと確信しています。

+0

私は1年前に同様の質問をしました。これまでのところ、 '' __del__'メソッドがまったく使用されない正当なシナリオを誰も指名することはできませんでした。私の知る限り、このメソッドは最初はPythonであってはいけません。それは何のためにも良いことであり、人々にクリーンアップのためにそれを使用できるという誤った印象を与えます。 – antred

8

必ずしもそうではありません。循環参照があるときに問題が発生します。イーライBenderskyは、彼のブログの記事でこれを説明するのは良い仕事をしていません:

+0

+1非常に良いリンク – dfa

+1

残念ながら、リンクされた記事は間違った結論を引き出します。 '__del__'は呼び出される保証はありません。まったく。周期的な参照だけではありません。また、** "循環参照はしばしば、悪いデザインの兆候です" ** WTF? – nosklo

0

あなたが循環参照にはなりません確信している場合は、そのように__del__を使用してOKです。できるだけ早く参照カウントがゼロになると、CPython VMはそのメソッドを呼び出してオブジェクトを破棄します。

循環参照を使用する場合は、非常に徹底的に考えて、弱い参照が役立つかどうかを確認してください。多くの場合、循環参照は悪い設計の最初の症状です。

オブジェクトの使用方法を制御できない場合は、__del__を使用すると安全でない可能性があります。

JPythonまたはIronPythonを使用する予定の場合、__del__は信頼性がありません。ガベージコレクションで最終的なオブジェクトの破棄が発生する可能性があります。これは制御できないものです。

私の意見では、__del__は、通常、完全に安全で良好です。しかし、多くの状況で、一歩前進させて、異なる視点から問題を見ることを試みる方が良いかもしれません。 try/exceptとcontextをうまく使うのは、もっとpythonicな解決策かもしれません。

関連する問題