ホームページ  >  記事  >  バックエンド開発  >  CPython のガベージ コレクターについて 1 つの記事で学習します

CPython のガベージ コレクターについて 1 つの記事で学習します

WBOY
WBOY転載
2022-10-12 15:32:351617ブラウズ

この記事では、Python に関する関連知識を提供します。主に CPython に関連する問題を紹介します。CPython のガベージ コレクターは、循環参照問題を解決するための Python の組み込みメソッドです。一緒に見てみましょう。皆様のお役に立てれば幸いです。

CPython のガベージ コレクターについて 1 つの記事で学習します

[関連する推奨事項: Python3 ビデオ チュートリアル ]

CPython のガベージ コレクター

CPython のガベージ コレクター(略して GC) は、循環参照問題を解決するための Python の組み込みメソッドです。デフォルトでは、常にバックグラウンドで実行され、時々魔法が機能するため、循環参照がメモリを詰まらせることを心配する必要はありません。

ガベージ コレクターは、CPython の作業メモリから循環参照オブジェクトを検索して削除するように設計されています。これは次の方法で行われます。

  • #循環参照オブジェクトを検出します

  • 最後の __del__ メソッドを呼び出します

  • 各 Remove から開始しますオブジェクトからのポインタ (ループの問題を解決するため)。ステップ 2 の後でループがまだ孤立している場合に限ります。

このプロセスが完了すると、すべてのオブジェクトの参照カウントが 0 になります。したがって、オブジェクトはメモリから削除されます。

これは自動的に動作しますが、実際には標準ライブラリからモジュールとしてインポートできます。例:

import gc

循環参照の検出

CPython のガベージ コレクターは、メモリ内に存在するさまざまなオブジェクトを追跡しますが、すべてのオブジェクトを追跡するわけではありません。いくつかのオブジェクトをインスタンス化し、ガベージ コレクターがそれらを収集するかどうかを確認できます。

>>> gc.is_tracked("a string")
False
>>> gc.is_tracked(["a", "list"])
True

オブジェクトにポインタを含めることができる場合、オブジェクトに循環参照構造の一部を形成する機能が与えられます。これはまさに、ガベージ ディテクタが検出して破棄するために存在する目的です。 Python では、このようなオブジェクトは「コンテナ オブジェクト」と呼ばれることがよくあります。

したがって、ガベージ コレクターは、循環参照の一部として存在する可能性のあるオブジェクトについて知る必要があります。文字列はそれができないため、「文字列」はガベージ コレクターによって追跡されません。 (これまで見てきたように) リストにはポインターを含めることができるため、['a', 'list'] が追跡されます。

ユーザー定義クラスのインスタンスは、いつでも任意のプロパティ (ポインター) を設定できるため、ガベージ コレクターによって追跡されます。

>>> Wade = MyNameClass("Wade")
>>> gc.is_tracked(Wade)
True

つまり、ガベージ コレクターは、循環参照を形成する可能性のあるすべてのオブジェクトを認識しています。循環参照が形成されているかどうかをどのようにして知るのでしょうか?

また、各オブジェクト内のすべてのポインターと、それらが指す場所も認識します。このアクションを見ることができます。

>>> my_list = ["a", "list"]
>>> gc.get_referents(my_list)
['list', 'a']

get_referents メソッド (トラバーサル メソッドとも呼ばれます) は、オブジェクトを受け取り、それに含まれるオブジェクト ポインター (その参照) のリストを返します。したがって、上記のリストには、文字列である各要素へのポインターが含まれています。

オブジェクトのループ内の get_referents メソッドを見てみましょう (ただし、オブジェクトは名前空間からアクセスできるため、まだ循環参照ではありません)。

>>> jane = MyNamedClass("Jane")
>>> bob = MyNamedClass("Bob")
>>> jane.friend = bob
>>> bob.friend = jane
>>> gc.get_referents(bob)
[{&#39;name&#39;: &#39;bob&#39;, &#39;friend&#39;: <__main__.MyNamedClass object at 0x7ff29a095d60>}, <class &#39;__main__

このループでは、bob が指すオブジェクトには、ボブの名前 (bob) とその友人 (jane MyNamedClass インスタンスも指す) を含むその属性辞書へのポインターが含まれていることがわかります。 bob.class はそのクラス オブジェクトを返すため、bob オブジェクトにはクラス オブジェクト自体へのポインターもあります。

ガベージ コレクターが実行されると、ガベージ コレクターが認識しているすべてのオブジェクト (つまり、gc.is_tracked を呼び出したときに True を返すオブジェクト) が名前空間から到達可能かどうかがチェックされます。これは、名前空間からのすべてのポインタ、およびそれらのポインタが指すオブジェクトへのポインタなどを追跡することによって行われ、コードからアクセスできるすべての全体のビューが構築されます。

これを実行した後、名前空間からアクセスできないオブジェクトがいくつかあることが GC によって検出された場合、これらのオブジェクトをクリアできます。

メモリ内に残っているオブジェクトは、ゼロ以外の参照カウントを持つ必要があることに注意してください。そうでない場合は、参照カウントのために削除されます。到達できなくても参照カウントが 0 以外のオブジェクトの場合、それらは循環参照の一部である必要があります。そのため、このようなことが発生する可能性を非常に懸念しています。

参照ループ、Jane と Bob に戻り、名前空間からポインターを削除して、このループを分離ループに変えてみましょう。

>>> del jane
>>> del bob

これで、ガベージ コレクターが解決する正確な状況がわかりました。 gc.collect() を呼び出すことで、手動のガベージ コレクションをトリガーできます。

>>> gc.collect()
Deleting Bob!
Deleting Jane!
4

デフォルトでは、ガベージ コレクターはこのアクションを時々自動的に実行します (CPython の実行中に、より多くのオブジェクトが作成および破棄されるため)。

上記のコード スニペットでは、出力には MyNamClass の __del__ メソッドからの print ステートメントが含まれており、最後に数字 (この場合は 4) が付いています。この数値はガベージ コレクター自体によって出力され、削除されたオブジェクトの数を示します。

【関連する推奨事項: Python3 ビデオ チュートリアル ]

以上がCPython のガベージ コレクターについて 1 つの記事で学習しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.imで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。