Section 6 / 12
オブジェクトの参照とリファレンスカウントの増減
Pythonは、メモリ管理のためにリファレンスカウントという仕組みを使用しています。これは、オブジェクトがどれだけ参照されているかを追跡する方法です。この教材では、オブジェクトの参照とリファレンスカウントの増減について学び、実際にコードを使ってその動作を確認します。
リファレンスカウントの基本
リファレンスカウントは、各オブジェクトがどれだけの参照を持っているかを示す整数値です。このカウントがゼロになると、そのオブジェクトはメモリから解放されます。以下のコードを使って、リファレンスカウントがどのように増減するかを見てみましょう。
サンプルコード
import sys
# 新しいオブジェクトを生成
a = [] # 空のリストを作成
print(f'リスト a のリファレンスカウント: {sys.getrefcount(a)}')
# リファレンスカウントを増やす
b = a # a を b に代入
print(f'リスト a のリファレンスカウント: {sys.getrefcount(a)}')
# リファレンスカウントを減らす
del b # b を削除
print(f'リスト a のリファレンスカウント: {sys.getrefcount(a)}')
コード解説
-
import sys- Pythonの
sysモジュールをインポートします。 sysモジュールにはsys.getrefcount()という関数が含まれ、引数として渡したオブジェクトの現在の参照カウント(リファレンスカウント)を取得できます。
- Pythonの
-
a = []- 空のリストオブジェクトを作成し、変数
aに代入します。 - この時点で、リスト
aは少なくとも1つの参照を持っています(a自体の参照)。
- 空のリストオブジェクトを作成し、変数
-
sys.getrefcount(a)sys.getrefcount(a)は、リストaのリファレンスカウントを返します。- ただし、関数呼び出し自体が一時的な参照を生成するため、実際のリファレンスカウントよりも常に1多い値を表示します。
-
b = a- 変数
bに変数aを代入すると、リストaへの参照が1つ増えます。 - この状態で、リファレンスカウントが1増加した結果を確認できます。
- 変数
-
del b- 変数
bを削除すると、リストaへの参照が1つ減ります。 - 結果として、リスト
aのリファレンスカウントが1減少します。
- 変数
参照の増減の実際の影響
次に、リファレンスカウントがどのようにオブジェクトの寿命に影響を与えるかを見てみましょう。以下のコードを実行してみてください。
import sys
class MyClass:
def __init__(self, name):
self.name = name
obj1 = MyClass("Object 1")
print(f'obj1 のリファレンスカウント: {sys.getrefcount(obj1)}')
obj2 = obj1 # 参照を増やす
print(f'obj1 のリファレンスカウント: {sys.getrefcount(obj1)}')
obj3 = obj1 # さらに参照を増やす
print(f'obj1 のリファレンスカウント: {sys.getrefcount(obj1)}')
del obj2 # 参照を減らす
print(f'obj1 のリファレンスカウント: {sys.getrefcount(obj1)}')
del obj3 # さらに参照を減らす
print(f'obj1 のリファレンスカウント: {sys.getrefcount(obj1)}')
# obj1 を削除する前にリファレンスカウントを確認
print(f'obj1 の最終リファレンスカウント: {sys.getrefcount(obj1)}')
del obj1 # 最後の参照を削除
# obj1 を削除した後にアクセスしないようにする
# print(f'obj1 のリファレンスカウント: {sys.getrefcount(obj1)}') # これはコメントアウトまたは削除
コード解説
-
class MyClass- クラス
MyClassを定義しています。初期化メソッド__init__でオブジェクトに名前を設定します。
- クラス
-
obj1 = MyClass("Object 1")- クラス
MyClassのインスタンスを生成し、変数obj1に代入します。 - この時点で、
obj1による参照が1つ作成されますが、sys.getrefcount関数が呼び出されたときの一時参照も加わるため、リファレンスカウントは 2 になります。
- クラス
-
obj2 = obj1とobj3 = obj1obj1を他の変数obj2とobj3に代入することで、リファレンスカウントがそれぞれ1ずつ増加します。- リファレンスカウントは最終的に 4 になります(
obj1,obj2,obj3, 一時参照)。
-
del obj2とdel obj3obj2やobj3を削除すると、obj1のリファレンスカウントがそれぞれ1ずつ減少します。- 参照が削除されるたびに、リファレンスカウントが更新されます。
-
最終確認と
del obj1- 最後に
obj1を削除することで、リファレンスカウントがゼロになり、オブジェクトがメモリから解放されます。
- 最後に
まとめ
リファレンスカウントは、Pythonのメモリ管理において非常に重要な役割を果たしています。オブジェクトの参照が増減することで、その寿命が決まります。次回は、リファレンスカウントによるメモリ解放の仕組みについて学んでいきましょう。