3

のPythonドキュメントでは、オブジェクトの参照カウントがゼロに減少したときに__del__オブジェクトのメソッドを呼び出すことができると説明されています。__del__それは常にすぐに(つまり同期的に)呼び出されますか?または、__del__メソッドが「将来のある時点で」呼び出される可能性はありますか?

さらに、この質問への答えは一般的にPythonに当てはまりますか?それとも、言語の実装にある程度の寛容さが与えられていますか?(私はCPythonを使用しています。)

この質問では、次のことを想定しています。

  • 問題のオブジェクトはから継承しobjectます。
  • 問題のオブジェクトにはカスタム__del__実装があります。
  • オブジェクトのカスタム__del__実装は、オブジェクトへの新しい参照を作成しません。
  • 問題のオブジェクトは、参照サイクルの一部ではありません。
  • 通訳はシャットダウン中です。

私の知る限り、このトピックについては多くの混乱があるようです。不必要な議論を回避するために、受け入れられない答えの例をいくつか挙げましょう。

  • 「使用しないでください__del__!紛らわしいです!」
  • 「使用しないでください__del__!「pythonic」ではありません。」
  • 「使用しないでください__del__。代わりにコンテキストマネージャーを使用してください。」
  • 信頼できる情報源を引用せずに、何が保証されているか、何が保証されていないかについて主張する答え。(他のSOの回答を自由に引用してください。ただし、それらを唯一のソースとして信頼しないでください。この場合の「信頼できる」とは、ドキュメント、信頼できる人物、またはCPythonソース自体からの何かを意味します。)

この質問を例で言い換えると、次のコードを検討してください。

class C(object):
    def __init__(self, i):
        self.i = i

    def __del__(self):
        print "C.__del__:", self.i

print "Creating list"
l = [C(0), C(1), C(2)]

print "Popping item 1"
l.pop(1)

print "Clearing list"
l = []

print "Exiting..."

これにより、次の出力が生成されます。

$ python test_del.py
Creating list
Popping item 1
C.__del__: 1
Clearing list
C.__del__: 2
C.__del__: 0
Exiting...

この例では、が同期的__del__ に呼び出されていることに注意してください。その動作は言語によって保証されていますか?(上記の前提条件に注意してください。)

4

2 に答える 2

3

Python言語リファレンス(Python 2.7.3エディション)、第3章、データモデルから

オブジェクトが明示的に破棄されることはありません。ただし、到達不能になると、ガベージコレクションされる可能性があります。実装では、ガベージコレクションを延期したり、完全に省略したりできます。まだ到達可能なオブジェクトが収集されない限り、ガベージコレクションの実装方法は実装品質の問題です。

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

于 2012-12-03T19:30:54.473 に答える
1

動作は言語によって保証されていません。たとえば、ガベージコレクションスキームに関するPyPyのドキュメントを__del__参照してください。このドキュメントには、PyPyで呼び出される時刻がCPythonとは異なることが明示的に記載されています。

オブジェクトが参照サイクルの一部ではない場合、この動作はCPythonで信頼できることを理解していますが、明示的な保証はありません。

于 2012-12-03T19:31:20.247 に答える