Python __del__とは?デストラクタの役割と使うべきでない理由
__del__は、オブジェクトが破棄されるときに呼ばれる特殊メソッド——いわゆるデストラクタです。
ただし「いつ呼ばれるか保証されない」ため、後始末の手段としては推奨されません。理由を順に見ていきます。
__del__の基本
class Resource:
def __init__(self, name):
self.name = name
def __del__(self):
print(f"__del__: {self.name}")
r = Resource("A")
print("delする前")
del r
print("delした後")
実行結果:
delする前
__del__: A
delした後
この例ではdel rの直後に呼ばれています。
しかしこれは偶然に近い——次の節から、そうならない場合を見ます。
del文は__del__を呼ぶとは限らない
r2 = Resource("B")
r3 = r2 # 参照が2つになった
del r2
print("参照が残っているので呼ばれない")
del r3
実行結果:
参照が残っているので呼ばれない
__del__: B
del r2は「変数名を消す」だけです。オブジェクト自体はr3から参照されているので生きています。
__del__が呼ばれるのは参照が1つも無くなったときです。
| 書き方 | 意味 |
|---|---|
del obj |
変数名を消す(__del__とは無関係) |
del obj[key] |
__delitem__を呼ぶ |
| 参照が0になる | __del__が呼ばれる |
循環参照では遅れる
import gc
class Node:
def __init__(self, name):
self.name = name
self.other = None
def __del__(self):
print(f"__del__: {self.name}")
x = Node("X")
y = Node("Y")
x.other = y
y.other = x
del x, y
print("→ すぐには呼ばれない")
gc.collect()
print("gc.collect()後")
実行結果:
→ すぐには呼ばれない
__del__: X
__del__: Y
gc.collect()後
互いに参照し合っていると参照数が0にならないため、ガベージコレクタが動くまで破棄されません。
いつ動くかはプログラム側から制御できません。「ファイルを閉じるのが数分後」ということが起こり得ます。
例外が握りつぶされる
class E:
def __del__(self):
raise ValueError("これは外に出ない")
e = E()
del e
print("プログラムは継続")
実行結果:
Exception ignored in: <function E.__del__ at 0x102b99e50>
Traceback (most recent call last):
...
ValueError: これは外に出ない
プログラムは継続
__del__の中の例外はtryで捕まえられません。標準エラー出力に「Exception ignored in」と表示されるだけです。
後始末に失敗しても、呼び出し側は失敗に気づけません。
withを使うべき理由
ここまでの問題はwith文ならすべて解決します。
class Resource:
def __enter__(self):
print("open")
return self
def __exit__(self, exc_type, exc_value, tb):
print("close")
return False
with Resource():
print("使用中")
実行結果:
open
使用中
close
__del__ |
with |
|
|---|---|---|
| 呼ばれるタイミング | 不定 | ブロックを抜けた瞬間 |
| 例外時 | 握りつぶされる | そのまま伝わる |
| 循環参照の影響 | 受ける | 受けない |
ファイル・DB接続・ロックの解放は、必ずwithで書いてください。
「Python __enter__・__exit__とは?with文で使えるクラスを作る方法」で解説しています。
それでも__del__を書くなら
「閉じ忘れたときの最後の保険」として書くことはあります。その場合の作法です。
- 本来は
close()やwithで解放する——__del__は保険に徹する - すでに解放済みかを確認してから処理する
- 中で例外を出さない(
tryで囲む) - 他のオブジェクトに触らない——終了処理中はすでに破棄されている場合がある
class Resource:
def __init__(self):
self.closed = False
def close(self):
if not self.closed:
self.closed = True
print("解放しました")
def __del__(self):
try:
self.close()
except Exception:
pass
標準ライブラリではweakref.finalizeという、より安全な仕組みも用意されています。
関連記事
近いテーマの記事です。あわせてどうぞ。
__del__のまとめ
- 参照が0になったときに呼ばれる
del objは名前を消すだけ——直接の関係はない- 循環参照ではGCが動くまで遅れる
- 中の例外は握りつぶされる
- 後始末は
with(__enter__/__exit__)を使う - 書くなら保険として、例外を出さずに


![Python __delitem__とは?del obj[key] を自作する方法 Gemini_Generated_Image_xmxzrsxmxzrsxmxz](/wp-content/uploads/2026/09/Gemini_Generated_Image_xmxzrsxmxzrsxmxz-150x150.jpg)


