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__()(デストラクタ)を実装すると、インスタンスが破棄される直前にそのメソッドが呼び出されます。このメソッドは、ファイルハンドルやネットワーク接続など、メモリ以外のリソースの後始末を行うために利用できます。
サンプルコード
次の例では、__del__()デストラクタが、破棄されようとしているインスタンスのクラス名を出力します。
#!/usr/bin/python3
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
補足:循環参照への対処
なお、CPythonの標準実装では、参照カウント方式に加えて、循環参照(互いに参照し合うオブジェクト同士)を検出して回収するための世代別ガベージコレクタも備えています。これにより、参照カウントだけでは回収できないオブジェクトのグループも適切に解放されるようになっています。
-
Pythonにおけるアンダースコア(_)の意味と使い方をわかりやすく解説
Pythonでは、アンダースコア(_)は特別な役割を持つ記号です。一見ただの文字に見えますが、実際にはインタープリタの動作や命名規則、数値リテラルの表記など、さまざまな場面で重要な働きをします。この記事では、Pythonでアンダースコアが使われる主な5つのケースを、コード例とともにわかりやすく解説します。1. インタープリタで直前の式の値を保持するPythonの対話モード(インタープリタ)では、直前に評価した式の結果が、特別な変数「_」に自動的に格納されます。計算結果をすぐに再利用したいときに非常に便利です。使用例>>> 12 + 10 22 >>> _ 2
-
Pythonでmkdir -pと同じようにディレクトリを再帰的に作成する方法
mkdir -pとは?UnixやLinuxのコマンドであるmkdir -pは、親ディレクトリが存在しない場合でも、必要な階層のディレクトリをまとめて一括作成できる便利なオプションです。また、指定したディレクトリがすでに存在していてもエラーにならず、そのまま処理が続行されます。Pythonでmkdir -pと同等の処理を行うにはPythonで同じことを実現するには、標準ライブラリのosモジュールにあるos.makedirs()関数を使用します。この関数に作成したいパスを渡すことで、中間の親ディレクトリも含めて再帰的にディレクトリを作成できます。exists_ok=True を指定するデフォルトで