Pythonではガベージコレクタという仕組みが背後で自動的に作動しており、不要になったメモリ領域は自動で解放されます。
Pythonでガベージコレクタとして動いている仕組みは現時点では二種類存在しています。
参考カウンタ
すべてのオブジェクトは内部的に参照カウントの値を持ちます。単純化した例を以下に示します。
python
1# 「10」というオブジェクト(厳密にはリテラル10を評価して得られるオブジェクト)をaというグローバル変数に束縛
2# これによって「10」の参照カウントの値は1になる
3a = 10
4
5# リストを作ってaをappendすることで、「10」の参照カウントの値は2になる
6lst = []
7lst.append(a)
8
参照カウントの値が0になったとき、そのオブジェクトはメモリ上から「解放」されます。
たとえばdel a
とdel lst
を実行してそれぞれの名前の束縛を解除すれば、「10」
のオブジェクトはメモリ上から消えます。
(lst
を消した結果「10」
も解放されるのが不思議に感じるかもしれませんが、これはlst
のオブジェクトを消すときにこちらで引き取って参照カウントの値をデクリメントしているからです。通常Pythonを書いているときはこれを意識する必要はありませんが、C拡張を書くときは気にする必要があります)。
gcモジュールで使えるGC
参照カウンタはエレガントな仕組みですが、循環参照として知られる問題があります。
python
1a = []
2b = []
3a.append(b)
4b.append(a)
5del a
6del b
a
とb
のlist
が互いに参照を持ち合っているので、それぞれの参照カウントの値が0にならず、これらは参照カウンタでは解放されません。
これを補うために、世代別ガベージコレクションが参照カウンタとは別に走っており、参照カウンタでは解放できなかったオブジェクトを解放します。
これも自動で行われるので、通常意識する必要はありません。
質問文のコードの場合
基本的には解放されると見て問題ありません。
python
1self.data = bytearray(['A','B','C'])
2newdata = bytearray(['V','W','X','Y','Z'])
3self.data = newdata # ここでbytearray(['A','B','C'])の参照カウントが0になり、解放される
もちろん、self.data
が実はプロパティで代入されたものをどこか他のところの記録しているとか、bytearray
が凶暴な代物で生成したオブジェクトを記録しているとか、マルチスレッドで処理が走っていてこの二行の間に運悪くself.data
を拾って他のところに参照を作ってしまうとか、色んな可能性は考えられますが、そういうことがない素直なプログラムであれば問題なく参照カウントで解放されるでしょう。
参考
はじめに — Python 3.8.2 ドキュメント
gc --- ガベージコレクタインターフェース — Python 3.8.2 ドキュメント
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/02/27 16:52