Python ガベージ コレクション メカニズムでの参照カウント

王林
リリース: 2023-04-10 13:51:08
転載
1292 人が閲覧しました

Python の __del__ マジック メソッドは、オブジェクトのターミネータとも呼ばれ、オブジェクトがメモリから削除される直前に呼び出されるメソッドです。実際にはメモリからオブジェクトを削除する仕事はしません。それがどのように起こるかは後で説明します。代わりに、このメソッドは、オブジェクトが削除される前に必要なクリーンアップを実行するために使用されます。たとえば、オブジェクトの作成時に開いていたファイルをすべて閉じます。

このセクションでは、例として次のクラスを使用します。

class MyNameClass:
def __init__(self, name):
self.name = name

def __del__(self):
print(f"Deleting {self.name}!")
ログイン後にコピー

上記の例では、初期化時に入力として名前を受け入れるクラスを定義しており、ファイナライザーが呼び出されると、関連するインスタンスの名前を出力して通知します。こうすることで、どのオブジェクトがいつメモリから削除されたかを知ることができます。

それでは、CPython はいつメモリからオブジェクトを削除することを決定するのでしょうか?これを行う方法は 2 つあります (CPython 3.10 時点では)。参照カウントとガベージ コレクションです。

参照カウント

Python でオブジェクトへのポインターがある場合、それはオブジェクトへの参照です。特定のオブジェクト a について、CPython は、 a を指す他のものがいくつあるかを追跡します。このカウンタがゼロに達した場合、他にオブジェクトが使用されていないため、オブジェクトをメモリから安全に削除できます。例を見てみましょう。

>>> Harward = MyNameClass("Harward")
>>> del Harward
Deleting Harward!
>>>
ログイン後にコピー

ここでは、新しいオブジェクト (MyNamedClass("Harward")) を作成し、それへのポインター (Harward =) を作成します。次に、Harwade を削除すると、この参照も削除され、MyNamedClass インスタンスの参照カウントは 0 になります。したがって、CPython はメモリからそれを削除することを決定します。そして、その直前に、その __del__ メソッドが呼び出され、上で見たメッセージが出力されます。

オブジェクトに対して複数の参照を作成した場合、オブジェクトを削除するにはすべての参照を削除する必要があります。

>>> bob = MyNameClass("Bob")
>>> bob_two = bob # creating a new pointer to the same object
>>> del bob # this doesn't cause the object to be removed...
>>> del bob_two # ... but this does
Deleting Bob!
ログイン後にコピー

もちろん、MyNamedClass インスタンス自体にポインターを含めることができます。結局のところ、これらは任意の Python オブジェクトであり、任意のプロパティを追加できます。例を見てみましょう。

>>> jane = MyNamedClass("Jane")
>>> bob = MyNamedClass("Bob")
>>> jane.friend = bob # now the "Jane" object contains a pointer to the "Bob" object...
>>> bob.friend = jane
ログイン後にコピー

上記のコード スニペットで行ったことは、いくつかの循環参照を設定することです。 Jane という名前のオブジェクトには Bob という名前のオブジェクトへのポインタが含まれており、その逆も同様です。次のことを行うと、事態は面白くなります。

>>> del jane
>>> del bob
ログイン後にコピー

これで、名前空間からオブジェクトへのポインターが削除されました。現在、これらの MyNameClass オブジェクトにはまったくアクセスできませんが、それらが削除されようとしていることを示す印刷メッセージは表示されません。これは、これらのオブジェクトが相互に含まれる参照をまだ持っているため、その参照カウントが 0 ではないためです。

ここで作成するのはループ分離です。この構造では、各オブジェクトはループ内に少なくとも 1 つの参照を持ち、それを存続させますが、ループ内のすべてのオブジェクトをアクセスした名前空間から削除することはできません。

ループ分離の直感的なパフォーマンス

次に、ループ分離を作成したときの直感的なパフォーマンスを示します。

まず、2 つのオブジェクトを作成します。各オブジェクトには名前空間内に名前があります。

Python ガベージ コレクション メカニズムでの参照カウント

次に、各オブジェクトにポインターを追加して 2 つのオブジェクトを接続します。

Python ガベージ コレクション メカニズムでの参照カウント

#最後に、両方のオブジェクトの元の名前を削除して、名前空間からポインターを削除します。この時点では、2 つのオブジェクトには名前空間からアクセスできませんが、各オブジェクトにはもう一方のオブジェクトへのポインターが含まれているため、それらの参照カウントはゼロではありません。

Python ガベージ コレクション メカニズムでの参照カウント

したがって、ランタイムの作業メモリから無駄なリサイクル不可能なオブジェクトを排除するには、参照カウントだけでは不十分であることは明らかです。ここで CPython のガベージ コレクターが登場します。

以上がPython ガベージ コレクション メカニズムでの参照カウントの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:51cto.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート