<一覧に戻る

リファレンスカウントによるメモリ解放

Pythonは自動的にメモリ管理を行いますが、その背後には「リファレンスカウント」という仕組みがあります。この教材では、リファレンスカウントによるメモリ解放の概念を理解し、実際のコードを通じてその動作を確認します。

リファレンスカウントとは

リファレンスカウントは、オブジェクトの参照が何回行われているかをカウントする仕組みです。各オブジェクトは、そのオブジェクトを参照する変数やデータ構造の数を追跡します。リファレンスカウントが0になると、オブジェクトは不要と判断され、メモリが解放されます。

サンプルコード

以下のサンプルコードを使って、リファレンスカウントの動作を確認します。

import sys

class MyObject:
    def __init__(self, value):
        self.value = value

# オブジェクトを作成
obj1 = MyObject(10)
print(f'obj1のリファレンスカウント: {sys.getrefcount(obj1)}')

# obj1を別の変数に代入
obj2 = obj1
print(f'obj1のリファレンスカウント: {sys.getrefcount(obj1)}')
print(f'obj2のリファレンスカウント: {sys.getrefcount(obj2)}')

# obj1の参照を削除
del obj1
print(f'obj2のリファレンスカウント: {sys.getrefcount(obj2)}')

# obj2の参照を削除
del obj2
# ここでobj2のリファレンスカウントは0になり、メモリが解放される

コード解説

  1. class MyObject

    • クラス MyObject を定義し、コンストラクタ __init__ でオブジェクトの属性 value を設定します。
  2. オブジェクト作成

    • obj1 = MyObject(10) によって、MyObject のインスタンスを生成し、変数 obj1 に代入します。
    • この時点で、obj1 による参照が1つ作成されます。ただし、sys.getrefcount(obj1) を呼び出す際の一時参照が加わるため、リファレンスカウントは 2 と表示されます。
  3. 別の変数に代入

    • obj2 = obj1 を実行すると、obj1 が参照しているオブジェクトへの参照が増加し、リファレンスカウントが1増加します。
    • この状態ではリファレンスカウントは 3 になります(obj1, obj2, 一時参照)。
  4. del obj1

    • del obj1 によって、obj1 が削除されますが、obj2 がまだオブジェクトを参照しているため、リファレンスカウントが1減少します。
    • この時点でリファレンスカウントは 2 になります(obj2 と一時参照)。
  5. del obj2

    • del obj2 によって、すべての参照が削除されます。
    • リファレンスカウントが0になり、オブジェクトがメモリから解放されます。
    • この段階でリファレンスカウントを確認するコードは含まれていませんが、オブジェクトへの参照が完全に無くなります。

まとめ

リファレンスカウントは、Pythonにおけるメモリ管理の基本的な部分です。この仕組みを理解することで、Pythonがどのようにメモリを管理しているかをより深く理解できるようになります。次のステップでは、リファレンスカウントの限界や循環参照の問題について考えていきましょう。

出力結果: