「for」ループを使用した辞書の反復


3138

私は次のコードに少し困惑しています:

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:
    print key, 'corresponds to', d[key]

分からないのはそのkey部分。Pythonは、辞書からキーを読み取るだけでよいことをどのように認識しますか?あるkeyPythonで特別な言葉は?それとも単に変数ですか?


3
新しい回答を投稿する前に、この質問にはすでに10以上の回答があることを考慮してください。回答が既存の回答に含まれない情報を提供していることを確認してください。
janniks

回答:


5393

key 単なる変数名です。

for key in d:

キーと値ではなく、ディクショナリ内のキーを単純にループします。キーと値の両方をループするには、以下を使用できます。

Python 3.xの場合:

for key, value in d.items():

Python 2.xの場合:

for key, value in d.iteritems():

自分でテストするには、単語keyをに変更しpoopます。

Python 3.xでは、iteritems()は単にに置き換えられましたitems()。これは、dictに裏打ちされたセットのようなビューを返しますiteritems()。これは2.7でも利用可能ですviewitems()

この操作items()は2と3の両方で機能しますが、2では辞書の(key, value)ペアのリストを返しitems()ます。これは、呼び出し後に発生するdictへの変更を反映しません。3.xで2.xの動作が必要な場合は、を呼び出すことができますlist(d.items())


158
このような値にアクセスしない見落とされた理由を追加すると、forループ内のd [key]により、キーが再度ハッシュされます(値を取得するため)。辞書が大きい場合、この余分なハッシュは全体の時間に追加されます。これについては、レイモンドヘッティンガーのテクニカルトークyoutube.com/watch?v=anrOzOapJ2E
quiet_penguinで2017

27
アイテムは予測できない順序で反復され、sortedそれを安定させるために必要であることを言及するのは理にかなっているかもしれません。
yugr 2018

5
@HarisankarKrishnaSwamy代替案は何ですか?
JoeyC 2018年

3
@yugrどうしてそんなこと言うの?ドキュメントは述べていますKeys and values are iterated over in insertion order. [ docs.python.org/3/library/...
下座トゥリ

4
@yugr Python 3.7以降、辞書は挿入順であり、これは言語機能です。stackoverflow.com/a/39980744/9428564を
Aimery

433

キーが特別な言葉であるというわけではありませんが、辞書は反復子プロトコルを実装しています。クラスでこれを行うことができます。たとえば、クラスイテレータの構築方法については、この質問を参照してください。

辞書の場合、Cレベルで実装されます。詳細はPEP 234で入手できます。特に、「辞書イテレータ」というタイトルのセクション:

  • ディクショナリは、ディクショナリのキーを反復する効率的なイテレータを返すtp_iterスロットを実装します。[...]これは、

    for k in dict: ...

    これは同等ですが、

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

    (ループまたは別のスレッドによる)辞書の変更に対する制限に違反していない限り。

  • さまざまな種類のイテレータを明示的に返すメソッドを辞書に追加します。

    for key in dict.iterkeys(): ...
    
    for value in dict.itervalues(): ...
    
    for key, value in dict.iteritems(): ...

    つまり、for x in dictはの省略形ですfor x in dict.iterkeys()

Pythonの3では、dict.iterkeys()dict.itervalues()およびdict.iteritems()サポートされなくなりました。使用しdict.keys()dict.values()そしてdict.items()その代わり。


207

反復処理dictあなたがここに見ることができるように、順不同でそのキーを反復処理:

編集:(これはもはやPython3.6当てはまりませんが、まだ動作が保証されてないことに注意してください)

>>> d = {'x': 1, 'y': 2, 'z': 3} 
>>> list(d)
['y', 'x', 'z']
>>> d.keys()
['y', 'x', 'z']

あなたの例では、それを使用することをお勧めしますdict.items()

>>> d.items()
[('y', 2), ('x', 1), ('z', 3)]

これにより、タプルのリストが表示されます。このように、それらの上にするときは、ループ、各タプルはアンパックにあるkv自動的に:

for k,v in d.items():
    print(k, 'corresponds to', v)

使用するkと、v上の変数名としてループする際にdictループの本体はわずか数行であれば非常に一般的です。より複雑なループの場合は、よりわかりやすい名前を使用することをお勧めします。

for letter, number in d.items():
    print(letter, 'corresponds to', number)

書式文字列を使用する習慣を身に付けることをお勧めします。

for letter, number in d.items():
    print('{0} corresponds to {1}'.format(letter, number))

11
Python 3.7リリースノートから:「dictオブジェクトの挿入順序の保存という性質は、Python言語仕様の公式な部分になりました。」
Gregory Arenius

86

key 単に変数です。

以下のためのPython2.X

d = {'x': 1, 'y': 2, 'z': 3} 
for my_var in d:
    print my_var, 'corresponds to', d[my_var]

...以上

d = {'x': 1, 'y': 2, 'z': 3} 
for the_key, the_value in d.iteritems():
    print the_key, 'corresponds to', the_value

以下のためのPython3.X

d = {'x': 1, 'y': 2, 'z': 3} 
for the_key, the_value in d.items():
    print(the_key, 'corresponds to', the_value)

63

for .. in ..-syntax を使用してディクショナリを反復処理すると、常にキーに対して反復処理されます(値はを使用してアクセスできますdictionary[key])。

キーと値のペアを反復するには、Python 2 for k,v in s.iteritems()とPython 3で使用しますfor k,v in s.items()


38
Pythonの3のために、それがあることに注意してくださいitems()代わりにiteritems()
アンドレアス・フェスター

32

これは非常に一般的なループイディオムです。in演算子です。いつ使用for key in dictする必要があるかfor key in dict.keys()については、David GoodgerのIdiomatic Pythonの記事(アーカイブコピー)を参照してください。


についてこれらのセクションを読んだinとき、演算子の部分は存在を確認する場所です。たぶん、このin is an operator情報を削除した方がいいでしょう。
ウルフ

19

「for」ループを使用した辞書の反復

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:
    ...

Pythonは、辞書からキーを読み取るだけでよいことをどのように認識しますか?Pythonではキーは特別な単語ですか?それとも単に変数ですか?

forループだけではありません。ここで重要な言葉は「繰り返し」です。

辞書は、キーと値のマッピングです。

d = {'x': 1, 'y': 2, 'z': 3} 

それを反復するときはいつでも、キーを反復します。変数名keyは説明を目的としたものであり、その目的に非常に適しています。

これはリスト内包表記で起こります:

>>> [k for k in d]
['x', 'y', 'z']

辞書をリスト(またはその他のコレクション型オブジェクト)に渡すと発生します。

>>> list(d)
['x', 'y', 'z']

Pythonが反復する__iter__方法は、必要なコンテキストで、反復子(この場合はキー反復子オブジェクト)を返すオブジェクト(この場合は辞書)のメソッドを呼び出すことです。

>>> d.__iter__()
<dict_keyiterator object at 0x7fb1747bee08>

これらの特別なメソッドを自分で使用するのではなく、それぞれの組み込み関数を使用して呼び出しますiter

>>> key_iterator = iter(d)
>>> key_iterator
<dict_keyiterator object at 0x7fb172fa9188>

イテレータには__next__メソッドがありますが、組み込み関数で呼び出しますnext

>>> next(key_iterator)
'x'
>>> next(key_iterator)
'y'
>>> next(key_iterator)
'z'
>>> next(key_iterator)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

イテレータが使い果たされると、それが発生しStopIterationます。これは、Pythonがforループ、リスト内包表記、ジェネレータ式、またはその他の反復コンテキストを終了することを認識する方法です。イテレータがレイズStopIterationすると、常にそれがレイズされます。もう一度イテレートしたい場合は、新しいイテレータが必要です。

>>> list(key_iterator)
[]
>>> new_key_iterator = iter(d)
>>> list(new_key_iterator)
['x', 'y', 'z']

辞書に戻る

多くの状況でディクテーションが繰り返されるのを見てきました。私たちが見たのは、ディクテーションを繰り返すたびに、キーを取得することです。元の例に戻る:

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:

変数名を変更しても、キーは取得されます。試してみよう:

>>> for each_key in d:
...     print(each_key, '=>', d[each_key])
... 
x => 1
y => 2
z => 3

値を繰り返し処理したい場合は.values、dicts のメソッドを使用するか、両方を一緒に使用する必要があります.items

>>> list(d.values())
[1, 2, 3]
>>> list(d.items())
[('x', 1), ('y', 2), ('z', 3)]

上記の例では、次のように項目を反復する方が効率的です。

for a_key, corresponding_value in d.items():
    print(a_key, corresponding_value)

しかし、学術目的では、質問の例は問題ありません。


17

私は、キーと値のペアを取得するためにdictを反復処理する必要があるユースケースと、自分がどこにいるかを示すインデックスも持っています。これが私のやり方です:

d = {'x': 1, 'y': 2, 'z': 3} 
for i, (key, value) in enumerate(d.items()):
   print(i, key, value)

キーの周りの括弧は重要であることに注意してください。括弧がないと、「アンパックするのに十分な値がありません」というValueErrorが発生します。


1
これは質問とどのように関連していますか?
jorijnsmit

8

CPythonの実装をdicttypeGitHub で確認できます。これは、dictイテレータを実装するメソッドのシグネチャです。

_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
             PyObject **pvalue, Py_hash_t *phash)

CPython dictobject.c


4

キーを反復処理する場合、速度は遅くなりますが、を使用する方が適していますmy_dict.keys()。あなたがこのようなことをやろうとした場合:

for key in my_dict:
    my_dict[key+"-1"] = my_dict[key]-1

プログラムの実行中にキーを変更しているため、ランタイムエラーが発生します。あなたが時間を短縮することに絶対にfor key in my_dict専念しているなら、その方法を使用してください、しかしあなたは警告されました;)。


2

これにより、値が昇順にソートされた出力が出力されます。

d = {'x': 3, 'y': 1, 'z': 2}
def by_value(item):
    return item[1]

for key, value in sorted(d.items(), key=by_value):
    print(key, '->', value)

出力:

ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.