web-dev-qa-db-ja.com

Pythonで辞書を反復処理するときに.iteritems()を呼び出す必要があるのはなぜですか?

辞書のキーと値のペアを反復処理するためにiteritems()を呼び出す必要があるのはなぜですか?すなわち

dic = {'one':'1', 'two':'2'}
for k, v in dic.iteritems():
    print k, v

辞書を反復処理するデフォルトの動作ではないのはなぜですか

for k, v in dic:
    print k, v
129
Falmarri

pythonコンテナCごとに、

for item in C:
    assert item in C

うまくいくでしょうyoin(ループ節)のある意味が他の意味(存在チェック)と完全に異なる意味を持っている場合、それは驚くべきことでしょうか?きっと!リスト、セット、タプルなどに対しては、自然にそのように機能します...

したがって、Cがディクショナリである場合、inforループでキー/値タプルを生成する場合、最小の驚きの原則により、inも包含チェックの左側のオペランドとしてそのようなタプルを取る必要があります。

それはどれほど便利でしょうか?まったく役に立たない、基本的にif (key, value) in Cif C.get(key) == valueの同義語にする-これは、実際にif k in Cの100倍もまれに実行した、または実行したいと思うチェックだ- 手段、キーの存在を確認のみ、値を完全に無視します。

一方、キーだけでループしたいのは非常に一般的です、例えば:

for k in thedict:
    thedict[k] += 1

値も持つことは特に助けにはなりません:

for k, v in thedict.items():
    thedict[k] = v + 1

実際にはやや不明瞭で簡潔です。 (itemsはキー/値のペアを取得するために使用する「適切な」メソッドの元のスペルでした。残念ながら、そのようなアクセサがリスト全体を返したときに戻っていたため、代替スペルをサポートするために導入され、iteritemsでした-Python 3では、以前のPythonバージョンとの後方互換性の制約が大幅に弱められ、再びitemsになりました)。

170
Alex Martelli

私の推測:完全なタプルを使用すると、ループ処理がより直感的になりますが、inを使用してメンバーシップをテストする場合はそれほど直感的ではありません。

if key in counts:
    counts[key] += 1
else:
    counts[key] = 1

inのキーと値の両方を指定する必要がある場合、そのコードは実際には機能しません。キーと値の両方が辞書にあるかどうかを確認するユースケースを想像するのは大変です。キーのみをテストする方がはるかに自然です。

# When would you ever write a condition like this?
if (key, value) in dict:

in演算子とfor ... inが同じアイテムを操作する必要はなくなりました。実装に関しては、それらは異なる操作です(__contains__ vs. __iter__)。しかし、そのわずかな矛盾はやや混乱を招き、ましてや矛盾が生じます。

9
John Kugelman