Pythonのガベージコレクションとは?参照カウントの仕組みをわかりやすく解説
Pythonのメモリ管理は非常にシンプルです。メモリの割り当てと解放は自動的に行われるため、開発者が細かいメモリ管理を意識する必要はほとんどありません。このメモリ管理の仕組みの一つがガベージコレクションです。本記事では、ガベージコレクションの基本概念から参照カウントの動作まで、具体例を交えながら詳しく解説していきます。
ガベージコレクションとは
ガベージコレクションとは、実行中のプログラムがそれ以上使用しなくなったメモリ領域を自動的に検出し、解放するプロセスのことです。ガベージコレクションによって解放されたメモリは、他のプログラムが再び利用できるようになります。
Pythonがメモリ管理に採用している主な方式は、次の2つです。
- 参照カウント(Reference Counting)
- ガベージコレクション(Garbage Collection)
Pythonのガベージコレクションは完全に自動で動作しますが、言語によっては開発者が自らオブジェクトを解放する必要があるものもあります。なお、Pythonでも必要に応じてdel文を使ってオブジェクトを手動で削除することが可能です。
>>> x = 9
>>> print(x)
9
>>> del x
>>> print(x)
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
print(x)
NameError: name 'x' is not defined
上記の例では、まず変数xを定義して値を出力しています。その後、実行時にオブジェクトを削除し(Pythonではすべてがオブジェクトとして扱われます)、再度出力を試みています。
プログラムの最初の2行の時点では、オブジェクトxは有効に存在しています。しかし、del xによってオブジェクトを削除した後は、もはやアクセスできず、NameErrorが発生します。
このように、Pythonのガベージコレクションは完全に自動化されており、開発者が特別な処理を行う必要はありません。次に、別の例を使ってこの仕組みをさらに掘り下げてみましょう。
参照カウントの仕組み
前述のコード例のように、Pythonのすべてのオブジェクトは参照カウントと型へのポインタを持っています。
参照カウントは、オブジェクトの使い方に応じて変化します。たとえば、オブジェクトxを別の変数yに代入すると、参照カウントは2に増加します。
>>> some_list = [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> # 参照カウント = 1 >>> other_list = some_list >>> # 参照カウント = 2 >>> # 関数の引数として渡しても参照カウントは増加する >>> list_total = sum(some_list) >>> # リストに格納した場合も参照カウントは増加する >>> list_of_list = [some_list, some_list, some_list] >>> >>> # オブジェクト"some_list"の参照カウントを確認 >>> import sys >>> sys.getrefcount(some_list) 6
これは、Pythonのメモリ管理における参照カウントの動きを理解するのに良い例です。オブジェクト「some_list」を作成すると参照カウントは1になり、別の変数への代入で2、関数の引数として渡すことで3、そしてリスト内に3回格納されることで合計6になります。実際にsys.getrefcount()で参照カウントを確認すると、6が返されます。
なお、sys.getrefcount()関数自体が一時的な参照を作るため、実際のカウントより1大きい値が返るという点にも注意しておきましょう。
>>> import sys
>>> sys.getrefcount(some_list)
6
>>>
>>> del list_of_list
>>> sys.getrefcount(some_list)
3
>>> del some_list
>>> sys.getrefcount(some_list)
Traceback (most recent call last):
File "<pyshell#17>", line 1, in <module>
sys.getrefcount(some_list)
NameError: name 'some_list' is not defined
del list_of_listを実行してリストを削除すると、参照カウントは3に減少します。さらにdel some_listで元のオブジェクトを削除すると、オブジェクトは完全に解放され、以降はアクセスできなくなります。
このように、Pythonではオブジェクトへの参照がすべてなくなった時点で、そのメモリは自動的に回収されます。開発者はメモリリークを心配することなく、本来のロジックの実装に集中できるのが大きなメリットです。
-
Pythonのオブジェクト比較を徹底解説:「is」と「==」演算子の違い
本記事では、Pythonにおけるオブジェクト比較の方法として、「is」演算子と等価演算子「==」の違いについて詳しく解説します。 この2つの演算子は似ているようで、実はまったく異なる役割を持っています。それぞれの動作の仕組みを正しく理解することは、バグの少ないPythonコードを書く上で非常に重要です。 「==」と「is」の基本的な違い 等価演算子(==)は、渡されたオブジェクトの値が等しいかどうかを判定します。つまり、2つのオブジェクトがメモリ上のどこに格納されていようと、中身の内容が同じであれば「等しい」とみなされます。 一方、is 演算子は、2つのオブジェクトが同一の参照(同じメモリ上の
-
Pythonのtimetuple()メソッドとは?struct_timeオブジェクトの基本と使い方
Pythonでは、datetime.dateインスタンスが持つtimetuple()メソッドを呼び出すと、time.struct_time型のオブジェクトが返されます。struct_timeは名前付きタプル(named tuple)の一種で、インデックス番号だけでなく、属性名を使って各フィールドにアクセスできるのが特徴です。struct_timeオブジェクトの構成要素struct_timeオブジェクトには、日付と時刻の両方を表す属性が含まれており、さらに夏時間(DST:Daylight Saving Time)が有効かどうかを示すフラグも持っています。timetuple()関数が返す名前付きタ