Python辞書ループ RuntimeError: 反復中に辞書のサイズが変更されたエラー解析
上記のような状況で、プログラムを実行すると、エラーは次のように報告されます。
RuntimeError: dictionary changed size during iteration
分析
Pythonの辞書は、ハッシュテーブルを使って実装されていることが分かっています。ハッシュテーブルは、キーにハッシュ関数を適用してインデックスを取得する配列です。
for cn_id in cn_map_info:
この方法では、辞書はイテレータによって走査されますが、要素の追加や削除など走査の途中で変更すると、走査が終了して
dictionary changed size during iteration
例外が発生します。
通常の使用では、Pythonはイテレータを使用することを推奨していることを知っています。
for k in xdict
という形式をとります。次に、トラバーサル中にコンテナ内の要素を削除することは、C++ STL や Python のようなライブラリでは推奨されません。これは、しばしば設計ソリューションに問題があることを示しているからで、Python に対応する特別な要件として、すべてのライブラリで
xdict.key()
を使用してコピーを作成します。最後に、すべてのPythonコンテナはスレッドセーフを約束していません。複数のスレッドでこれを行う必要があり、それ自体がロックされていなければならないことも、ビジネスコードの設計に問題があることを示しています。
しかし、"traversal" で特定の要素を削除するという特殊なケースから、"dict のトラバースでは、" の使用が発生します。
for k in d.keys()
という習慣がありますが、通常のトラバーサルでは、やはり
for k in xdict
効率的なPythonicのアプローチ。
また、"traversal"で要素を削除する必要がある場合、Pythonicのアプローチは
xdict = {k, v for adict.iteritems() if v ! = 0}
または
alist = [i for i in alist if i ! = 0]
Python辞書の実装原理。 https://harveyqing.gitbooks.io/python-read-and-write/content/python_advance/python_dict_implementation.html
解決方法
解決策は、辞書のキーを基準にして、値を変えても反復処理の継続に影響しないように反復処理することです。
Python2 解決方法は以下の通りです。
for cn_id in cn_map_info.keys():
if cn_id not in monitor_id_list:
del(cn_map_info[cn_id])
for cn_id in cn_map_info.keys()
key
この方法は、リストを経由して、それぞれの
for cn_id in list(cn_map_info.keys()):
if cn_id not in monitor_id_list:
del(cn_map_info[cn_id])
(cn_map_info.keys()が返すリスト)のように、トラバーサル処理が暴走しないようにするためです。
パイソン3 解決方法は以下の通りです。
nock:lab nock$ python2.6
Python 2.6.9 (unknown, Jul 14 2015, 19:46:31)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> monitor_id_list = [12, 13, 14, 16, 19, 20]
>>> cn_map_info = {12: 'taiwan', 13: 'hongkong', 15: 'guizhou'}
>>> print(cn_map_info.keys())
[12, 13, 15]
>>> exit()
nock:lab nock$ python3
Python 3.5.1 (default, Dec 26 2015, 18:08:53)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> monitor_id_list = [12, 13, 14, 16, 19, 20]
>>> cn_map_info = {12: 'taiwan', 13: 'hongkong', 15: 'guizhou'}
>>> print(cn_map_info.keys())
dict_keys([12, 13, 15])
>>> print(list(cn_map_info.keys()))
[12, 13, 15]
繰り返しますが、Python3はリスト内のすべてのキーをループします。これは元の辞書と衝突しないので、探索がクラッシュすることはありません。
なぜPython 3ではlist()が必要なのですか? 解析 は以下の通りです。
xdict.keys()
Python2 では、問題は単純明快です。
xdict.keys()
はリストを直接返しますが、Python3 では
xdict.keys()
は辞書のキーオブジェクトを返します。
この記事を書いたのは
空洞化
で作成した
クリエイティブ・コモンズ・ライセンス 4.0
ライセンスに関する国際ライセンス
当サイトに掲載されている記事は、特に断りのない限り、すべてオリジナルまたは翻訳であり、転載の際には必ず属性を明記してください
最終編集日 2018年04月17日 01時07分
関連
-
[解決済み】DataFrame のコンストラクタが正しく呼び出されない
-
[解決済み] ValueError : 閉じたファイルへのI/O操作
-
[解決済み] [Solved] ImportError: Queue'という名前のモジュールがない
-
[解決済み】Pythonが'list'オブジェクトをstrに変換できないエラー [終了しました]
-
numpyの使用におけるよくある誤り
-
[解決済み] return list.sort()」は、なぜリストではなくNoneを返すのですか?
-
[解決済み] 動的属性を持つクラスに対するPylint警告E1101: 'Instance of .. has no ... member'を回避する。
-
[解決済み] Python3、eval()に代わる最良の選択肢は?(式としての入力)
-
python encountered ValueError: check_hostname requires server_hostname 解決法
-
python reports UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 4: ordinal not in range.
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Pythonコードの可読性を向上させるツール「pycodestyle」の使い方を詳しく解説します
-
[解決済み】super()がエラーで失敗する。親がオブジェクトを継承していない場合、TypeError "argument 1 must be type, not classobj" が発生する。
-
pygame.error:ビデオシステムが初期化されていない場合の解決方法
-
[解決済み] "int() can't convert non-string with explicit base" しかし、それは文字列である。
-
[解決済み] super().method() と super(self.__class__,self).method() の違いについて [重複]。
-
[解決済み] Pythonです。ラムダ関数に1つだけ変数を渡すには?
-
[解決済み] scipy.sparse.csr_matrixの例を理解できない。
-
[解決済み] AttributeError: 'list' オブジェクトには 'copy' という属性がありません。
-
TypeError: データ型が理解できない
-
scipy.stats.multivariate_normalガウス分布