1. ホーム
  2. プログラミング言語
  3. パイソン

に対する解決策です。RuntimeError: 巡回辞書操作時に反復処理中に辞書サイズが変更された。

2022-01-21 04:05:11

社員情報の追加、削除、チェックの業務を行っているときに、ユーザーの入力IDでユーザー情報を削除する要件がありました。ファイルからユーザー情報を抽出し、ユーザーIDをキー、その他ユーザーに関する情報を値とする辞書に格納しました。辞書をループしているときに、ユーザーIDが辞書のキーと等しくなると、情報が削除され、RuntimeError: dictionary changed size during iterationというエラーとともに削除が報告されます。

for key in staff_info:
    if user_id == key:
        print(key)
        staff_info.pop(key)
        id_exist = True

参考:https://www.python.org/dev/peps/pep-0234/#dictionary-iterators

で公式サイトの解説をご覧ください。

辞書は  tp_iter  このスロットは、辞書のキーに対して反復処理を行う効率的なイテレータを返します。このような反復の間、辞書は修正されてはいけません。ただし、既存のキーに対する値の設定は許可されます(削除や追加は許可されません。  update()  メソッド)。つまり、次のように書くことができる。

for k in dict: ...


と同等であるが、より高速である。

for k in dict.keys(): ...


ただし、(ループや他のスレッドによる)辞書の修正に関する制限に違反しない限りである。

すでに存在するキーに値をセットする場合を除き、ループしている間は複数の辞書を削除したり更新したりできない、ということです。 と for k in dict.keys(): ... 効果は同じですが、前者の方が高速です。

では、テストしてみましょう。

a = {'a': 1, 'b': 0, 'c': 1, 'd': 0}

for key in a:
    print(key, a[key])

for key in a.keys():
    print(key, a[key])

# Both loops have the same effect

print(a.keys()) # dict_keys(['a', 'b', 'c', 'd'])
print(a) # {'a': 1, 'b': 0, 'c': 1, 'd': 0}

a.keysがdict_keys型であることを除けば、これらは同じ効果を持ちます。

すると、リスト形式への変換はOKという解答が出てきました。

for key in list(staff_info.keys()):  
    if user_id == key:
        print(key)
        staff_info.pop(key)
        id_exist = True

Youdao辞書
for k in dict: ...
詳細 <スパン X
kのディクショナリータイプ:...