Pythonのガベージコレクション徹底解説!オブジェクトの破棄と参照カウントの仕組み
Pythonにおけるオブジェクトの破棄とガベージコレクション
Pythonでは、不要になったオブジェクト(組み込み型やクラスのインスタンス)を自動的に削除し、メモリ領域を解放します。このように、Pythonが定期的に使用されなくなったメモリブロックを回収する仕組みのことを「ガベージコレクション(Garbage Collection)」と呼びます。
Pythonのガベージコレクタはプログラムの実行中に動作しており、オブジェクトの参照カウントがゼロになったタイミングで起動されます。参照カウントは、そのオブジェクトを指す別名(エイリアス)の数に応じて変化します。
参照カウントが増えるのは、オブジェクトに新しい名前が割り当てられたとき、あるいはリスト・タプル・辞書などのコンテナに格納されたときです。逆に、del文で削除されたとき、参照が別のオブジェクトに再割り当てされたとき、参照がスコープ外に出たときには、参照カウントが減少します。そして参照カウントがゼロになると、Pythonはそのオブジェクトを自動的に回収します。
参照カウントの変化を追う例
a = 40 # オブジェクト <40> を作成
b = a # <40> の参照カウントが増加
c = [b] # <40> の参照カウントが増加
del a # <40> の参照カウントが減少
b = 100 # <40> の参照カウントが減少
c[0] = -1 # <40> の参照カウントが減少
通常、ガベージコレクタが孤立したインスタンスを破棄してメモリを解放する瞬間を目にすることはありません。しかし、クラスには特殊メソッド __del__()(デストラクタ)を実装することができます。このメソッドは、インスタンスが破棄される直前に呼び出されるため、ファイルハンドルやネットワーク接続など、メモリ以外のリソースの後始末に活用できます。
サンプルコード
次の例では、__del__() デストラクタが、破棄されようとしているインスタンスのクラス名を出力します。
#!/usr/bin/python
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __del__(self):
class_name = self.__class__.__name__
print(class_name, "destroyed")
pt1 = Point()
pt2 = pt1
pt3 = pt1
print(id(pt1), id(pt2), id(pt3)) # 各オブジェクトのIDを出力
del pt1
del pt2
del pt3
実行結果
上記のコードを実行すると、次のような出力が得られます。
3083401324 3083401324 3083401324
Point destroyed
すべての変数(pt1〜pt3)が同じオブジェクトIDを持っていることから、3つの名前が同一のインスタンスを参照していることが分かります。delによってすべての参照が削除され、参照カウントがゼロになった時点で、初めて「Point destroyed」が出力され、オブジェクトが破棄されます。
補足: 実際の開発では、クラスは独立したファイルに定義し、メインプログラムから import 文を使って読み込むのが望ましい設計とされています。また、__del__() の実行タイミングはインタプリタの実装に依存するため、確実なリソース解放が必要な場面では with 文(コンテキストマネージャ)の利用も検討しましょう。
-
Pythonで配列の反転数(転倒数)をカウントする方法
はじめに この記事では、配列内の反転(インバージョン)をカウントする問題とその解決策について詳しく解説します。 問題定義 問題: リストが与えられたとき、その中に含まれる反転の数をカウントして表示します。 反転数とは、配列を昇順にソートされた状態にするために必要な入れ替え(スワップ)の回数を表す指標です。具体的には、i < j かつ arr[i] > arr[j] を満たす要素のペア(i, j)の総数として定義されます。 実装例 # 反転数をカウントする関数 def InvCount(arr, n): inv_count = 0 for i in range(n
-
Pythonのファイルオブジェクトとは?open関数によるファイル操作の基本を徹底解説
Pythonでは、ファイルを読み書きする際に特別なライブラリをインポートする必要はありません。ファイル操作は言語にネイティブに組み込まれているためです。 まず最初に行うのは、組み込み関数 open() を使ってファイルオブジェクトを取得することです。open() 関数はファイルを開き、ファイルオブジェクトを返します。このファイルオブジェクトには、開いたファイルから情報を取得したり、内容を操作したりするためのメソッドや属性が含まれています。 ファイルとは何か? ファイル操作を行う前に、「ファイルとは何か」を理解しておきましょう。ファイルとは、関連する情報を保存するためにディスク上に確保された「名