RuntimeError: dictionary changed size during iteration の原因と直し方
辞書をイテレート中にキーを追加・削除すると発生する例外です。リストと違い、辞書はサイズの変化を検出して例外を投げます。
エラーメッセージの読み方
Traceback (most recent call last):
main.py- ファイル名
2- 行番号 — 実際にクラッシュした行
<module>- 発生場所 — <module> ならトップレベル、関数名ならその関数の中
RuntimeError- 例外クラス — 何が起きたか。ここを検索するのが最短です
dictionary changed size during iteration- 詳細メッセージ — どの値が問題だったか
このエラーが出る典型パターン
パターン1
1 scores = {"a": 1, "b": 0, "c": 3} 2 for key in scores : ^ 3 if scores[key] == 0: 4 del scores[key] 5 print(scores)
Traceback (most recent call last):
File "main.py", line 2, in <module>
for key in scores:
^^^^^^
RuntimeError: dictionary changed size during iteration
辞書はイテレート中にサイズが変わることを検出すると例外を投げます。安全に削除するには、先にキーのコピー(list())を作ってそちらをイテレートします。
直し方: scores を list(scores) にします。
広告
広告スロット(未設定)
パターン2
1 inventory = {"apple": 5, "banana": 0, "cherry": 2} 2 for item in inventory : ^ 3 if inventory[item] == 0: 4 del inventory[item] 5 print(inventory)
Traceback (most recent call last):
File "main.py", line 2, in <module>
for item in inventory:
^^^^^^^^^
RuntimeError: dictionary changed size during iteration
在庫が0の商品を削除するような処理でよく起きます。辞書のキー一覧を先にlist()でコピーしておけば安全です。
直し方: inventory を list(inventory) にします。
パターン3
1 settings = {"a": True, "b": False, "c": True} 2 for key in settings : ^ 3 if not settings[key]: 4 del settings[key] 5 print(settings)
Traceback (most recent call last):
File "main.py", line 2, in <module>
for key in settings:
^^^^^^^^
RuntimeError: dictionary changed size during iteration
真偽値フラグの整理でも同じです。Falseの項目を削除する処理はよく書かれるパターンなので、覚えておくと役に立ちます。
直し方: settings を list(settings) にします。
よくある誤解
リストの要素削除は例外にならず静かに壊れますが、辞書は検出して例外を投げてくれます。この挙動の違いを知らないと混乱します。
まとめ
RuntimeError: dictionary changed size during iterationは上級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。