Pythonは、メモリ管理のためにリファレンスカウント(参照カウント)を使用しています。リファレンスカウントとは、オブジェクトがメモリ内でどのくらいの数の参照(リファレンス)を持たれているかを追跡する仕組みです。具体的には、オブジェクトが生成されると、そのオブジェクトに対するリファレンスカウントが1になります。新しい参照が作られるたびにカウントが増加し、参照が削除されるとカウントが減少します。
この仕組みにより、メモリの自動管理が行われ、オブジェクトがもはや必要でなくなったときに自動的にメモリを解放することが可能になります。
以下のサンプルコードを通じて、リファレンスカウントの基本的な動作を理解しましょう。
import sys
class MyClass:
def __init__(self, value):
self.value = value
# オブジェクトの生成
obj1 = MyClass(10)
# リファレンスカウントを表示
print(f"obj1のリファレンスカウント: {sys.getrefcount(obj1)}") # sysモジュールを使用
# 新しい参照を作成
obj2 = obj1
print(f"obj1のリファレンスカウント: {sys.getrefcount(obj1)}")
# 参照を削除
del obj2
print(f"obj1のリファレンスカウント: {sys.getrefcount(obj1)}")
クラスの定義
MyClass
というクラスを定義し、初期化メソッド__init__
でvalue
という属性を設定しています。このクラスは、リファレンスカウントの実験に使用するだけのシンプルな構造です。オブジェクトの生成
obj1 = MyClass(10)
でMyClass
のインスタンスを生成しています。この時点で、Python内部では少なくとも1つの参照が存在します。 sys.getrefcount()
を使用すると、実際のリファレンスカウントよりも1多い値が返されます。これは、getrefcount
関数に引数を渡すことで、一時的な参照が追加されるためです。リファレンスカウントの確認
sys.getrefcount(obj1)
を使用してobj1
のリファレンスカウントを確認します。 obj1
自身の参照と、sys.getrefcount
関数呼び出し時の一時的な参照を含むためです。新しい参照の作成
obj2 = obj1
を実行すると、obj1
の参照がもう1つ増えます。このとき、リファレンスカウントが1増加します。 obj1
の参照、obj2
の参照、そして関数呼び出し時の一時的な参照の合計)参照の削除
del obj2
を実行すると、obj2
が削除され、obj1
の参照が1つ減少します。この状態でリファレンスカウントを確認すると「2」と表示されます。 obj1
は有効であるため、引き続き使用可能です。リファレンスカウントは、Pythonのメモリ管理において非常に重要な役割を果たしています。この仕組みにより、オブジェクトの使用状況に応じてメモリが効率的に管理され、プログラマーが手動でメモリを解放する必要が少なくなります。しかし、リファレンスカウントには限界があり、特に循環参照の問題が存在します。この問題については次のセクションで詳しく説明します。