Python2のdict.items()とdict.iteritems()の違いは何ですか?


705

との間に適用可能な違いはdict.items()ありdict.iteritems()ますか?

Python docsから:

dict.items():辞書の(キー、値)ペアのリストのコピーを返します

dict.iteritems():辞書の(キー、値)ペアのイテレータを返します

以下のコードを実行すると、それぞれが同じオブジェクトへの参照を返すようです。私が見逃している微妙な違いはありますか?

#!/usr/bin/python

d={1:'one',2:'two',3:'three'}
print 'd.items():'
for k,v in d.items():
   if d[k] is v: print '\tthey are the same object' 
   else: print '\tthey are different'

print 'd.iteritems():'   
for k,v in d.iteritems():
   if d[k] is v: print '\tthey are the same object' 
   else: print '\tthey are different'   

出力:

d.items():
    they are the same object
    they are the same object
    they are the same object
d.iteritems():
    they are the same object
    they are the same object
    they are the same object

41
それは基本的にそれらが計算される方法の違いです。items()一度にすべてのアイテムを作成し、リストを返します。iteritems()ジェネレータを返します。ジェネレータは、next()呼び出されるたびに一度に1つの項目を「作成」するオブジェクトです。
Joel Cornett、

9
特定のケースでd[k] is vは、pythonは-5から256までのすべての整数の整数オブジェクトの配列を保持するため、常にTrueを返します。docs.python.org/ 2 / c-api / int.htmlその範囲でintを作成すると、実際には、既存のオブジェクトへの参照を取得するだけです。 >> a = 2; b = 2 >> a is b Trueただし、>> a = 1234567890; b = 1234567890 >> a is b False
t_tia '23

3
@the_wolf質問で参照しているドキュメントのpythonバージョンを追加した方がよいと思います。
Lorenzo Belli 2017年

2
Python 3でにiteritems()変更さiter()れましたか?上記のドキュメントのリンクは、この回答と一致していないようです。
ガブリエルステープルズ2018

3
正確には、@ GabrielStaples。iteritems()は、Python 3の辞書から削除されました。ただし、同じ効果を得るにはiter()を使用します。例えばiter(dict.items())。pep 469:python.org/dev/peps/pep-0469
Zim

回答:


863

それは進化の一部です。

もともと、Python items()はタプルの実際のリストを作成し、それを返しました。それは潜在的に多くの余分なメモリを消費する可能性があります。

次に、ジェネレーターが一般的に言語に導入され、そのメソッドはという名前のイテレータージェネレーターメソッドとして再実装されましたiteritems()。オリジナルは下位互換性のために残されています。

Python 3の変更点の1つは items()、反復子を返すようになり、リストが完全に作成されることはありません。Python 3 ではPython 2.7と同様に機能するiteritems()ためitems()、この方法もなくなりましたviewitems()


159
進化の一歩を逃したことに注意してください。Py3の動作はと同じではありませんiteritems()。実際には、dictへの変更を反映する完全なシーケンスプロトコルオブジェクトを作成します(冗長リストではなく、dict自体によってサポートされます)viewitems()。これは、2.7にとして移植されています。
lvc

3
これについて詳しく知りたいのですが、google-fuで失敗しています。誰かが私にこれをよりよく理解するのに役立つドキュメント、記事、またはソースを教えてもらえますか?@lvc?
2016

10
@Stewの変更はPEP 3106で説明されており、python 3.0の新機能に
Tadhg McDonald-Jensen

1
この古代の質問について詳しく説明して申し訳ありませんが、Python 2.xではiteritems()常に望ましいことでitems()ある私は正しく理解していますか?
RubenGeert

2
@RubenGeertほとんどの場合、それは問題ではありません。本当に大きな口述の場合、それが望ましいかもしれません。
キース

95

dict.items()は2タプル([(key, value), (key, value), ...])のリストを返しますが、2タプルdict.iteritems()を生成するジェネレータです。前者は最初により多くのスペースと時間を必要としますが、各要素へのアクセスは高速ですが、2つ目は最初に少ないスペースと時間を必要としますが、各要素の生成には少し時間がかかります。


9
なぜそれらが異なると期待するのですか?
Ignacio Vazquez-Abrams

3
ドキュメントの「コピー」は、要素がコピーされることを意味しません(必要な場合は、を使用してくださいcopy.deepcopy)。これは、ディクショナリアイテムのコピーであることを意味します。その場合、キーまたはを追加/削除してitems = dct.items()変更すると、同じままになります。dctdct[k] = other_vitems
Dougal

4
特に明記されていない限り、Pythonの何もディープコピーではありません。
Karl Knechtel、2012

1
@ IgnacioVazquez-Abrams-「より多くの空間と時間」について:辞書のサイズが重要になります。{1:'one', 2:'two', ... }Webサーバーで繰り返し処理して結果を表示したい「大きな」辞書があるとします。Python 2.7の.items()vsの選択について、どの程度の規模で心配する必要があり.iteritems()ますか?
ユーザー

1
@buffer:よくわかりません。私の見積もりは15〜20アイテムですが、テストしていません。
Ignacio Vazquez-Abrams

64

Py2.x内

コマンドdict.items()dict.keys()および辞書のリストコピーdict.values()返します(k, v)ペア、キーと値を。コピーされたリストが非常に大きい場合、これは大量のメモリを消費する可能性があります。

コマンドdict.iteritems()dict.iterkeys()およびは、辞書のペア、キー、および値の反復子dict.itervalues()返します。(k, v)

コマンドdict.viewitems()dict.viewkeys()およびは、ディクショナリの変更を反映できるビューオブジェクトdict.viewvalues()返します。(つまり、アイテムにアイテムを追加するか、ディクショナリにペアを追加すると、ビューオブジェクトは同時に自動的に変更されます。)del(k,v)

$ python2.7

>>> d = {'one':1, 'two':2}
>>> type(d.items())
<type 'list'>
>>> type(d.keys())
<type 'list'>
>>> 
>>> 
>>> type(d.iteritems())
<type 'dictionary-itemiterator'>
>>> type(d.iterkeys())
<type 'dictionary-keyiterator'>
>>> 
>>> 
>>> type(d.viewitems())
<type 'dict_items'>
>>> type(d.viewkeys())
<type 'dict_keys'>

Py3.xにいる間

Py3.xでは、物事は唯一の存在であることから、よりクリーンでdict.items()dict.keys()そしてdict.values()利用できる、返したビューオブジェクトを同じようにdict.viewitems()にです。

だが

@lvcが指摘したように、ビューオブジェクトiteratorと同じではないため、Py3.xでイテレータを返したい場合は、次のように使用できますiter(dictview)

$ python3.3

>>> d = {'one':'1', 'two':'2'}
>>> type(d.items())
<class 'dict_items'>
>>>
>>> type(d.keys())
<class 'dict_keys'>
>>>
>>>
>>> ii = iter(d.items())
>>> type(ii)
<class 'dict_itemiterator'>
>>>
>>> ik = iter(d.keys())
>>> type(ik)
<class 'dict_keyiterator'>

34

あなたは尋ねました:「dict.items()とdict.iteritems()の間に適用可能な違いはありますか」

これは役立つかもしれません(Python 2.xの場合):

>>> d={1:'one',2:'two',3:'three'}
>>> type(d.items())
<type 'list'>
>>> type(d.iteritems())
<type 'dictionary-itemiterator'>

d.items()キーと値のペアのタプルのリストを返し、d.iteritems()辞書itemiteratorを返します。

リストとして、d.items()はスライス可能です。

>>> l1=d.items()[0]
>>> l1
(1, 'one')   # an unordered value!

しかし、__iter__メソッドはありません:

>>> next(d.items())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list object is not an iterator

イテレータとして、d.iteritems()はスライス可能ではありません

>>> i1=d.iteritems()[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'dictionary-itemiterator' object is not subscriptable

しかし、持っています__iter__

>>> next(d.iteritems())
(1, 'one')               # an unordered value!

したがって、アイテム自体は同じです。アイテムを配信するコンテナは異なります。1つはリスト、もう1つはイテレータ(Pythonのバージョンによって異なります...)

そのため、dict.items()とdict.iteritems()の間の該当する違いは、リストとイテレータの間の該当する違いと同じです。


15

dict.items()タプルのリストをdict.iteritems()返し、辞書のタプルの反復子オブジェクトをとして返します(key,value)。タプルは同じですが、コンテナーが異なります。

dict.items()基本的にすべての辞書をリストにコピーします。実行時間を比較するために、次のコードを使用してみてくださいdict.items()dict.iteritems()。違いがわかります。

import timeit

d = {i:i*2 for i in xrange(10000000)}  
start = timeit.default_timer() #more memory intensive
for key,value in d.items():
    tmp = key + value #do something like print
t1 = timeit.default_timer() - start

start = timeit.default_timer()
for key,value in d.iteritems(): #less memory intensive
    tmp = key + value
t2 = timeit.default_timer() - start

私のマシンでの出力:

Time with d.items(): 9.04773592949
Time with d.iteritems(): 2.17707300186

これは明らかにそれdictionary.iteritems()がはるかに効率的であることを示しています。


4

あなたが持っている場合

dict = {key1:value1, key2:value2, key3:value3,...}

ではPythonの2dict.items()コピーの各タプルを返す辞書IEのタプルのリスト[(key1,value1), (key2,value2), ...]。つまり、辞書全体がタプルを含む新しいリストにコピーされます。

dict = {i: i * 2 for i in xrange(10000000)}  
# Slow and memory hungry.
for key, value in dict.items():
    print(key,":",value)

dict.iteritems()辞書アイテム反復子を返します。返される項目の値も同じです。つまり(key1,value1), (key2,value2), ...、これはリストではありません。これは、ディクショナリアイテムの反復子オブジェクトです。つまり、メモリ使用量が少なくなります(50%減)。

  • 変更可能なスナップショットとしてリスト: d.items() -> list(d.items())
  • イテレータオブジェクト: d.iteritems() -> iter(d.items())

タプルは同じです。それぞれのタプルを比較して、同じになるようにしました。

dict = {i: i * 2 for i in xrange(10000000)}  
# More memory efficient.
for key, value in dict.iteritems():
    print(key,":",value)

パイソン3dict.items()イテレータオブジェクトを返します。dict.iteritems()が削除されたため、これ以上問題はありません。


4

dict.iteritemsPython3.xでなくなったのでiter(dict.items())、同じ出力とメモリ割り当てを取得するために使用します


1

Python 2と3の両方で機能するディクショナリのアイテムペアを反復する方法が必要な場合は、次のような方法を試してください。

DICT_ITER_ITEMS = (lambda d: d.iteritems()) if hasattr(dict, 'iteritems') else (lambda d: iter(d.items()))

次のように使用します。

for key, value in DICT_ITER_ITEMS(myDict):
    # Do something with 'key' and/or 'value'.

0

dict.iteritems():イテレータを提供します。ループの外側の他のパタ​​ーンでイテレータを使用できます。

student = {"name": "Daniel", "student_id": 2222}

for key,value in student.items():
    print(key,value)

('student_id', 2222)
('name', 'Daniel')

for key,value in student.iteritems():
    print(key,value)

('student_id', 2222)
('name', 'Daniel')

studentIterator = student.iteritems()

print(studentIterator.next())
('student_id', 2222)

print(studentIterator.next())
('name', 'Daniel')

-5

Python 2のdict.iteritems()は、Python 3のdict.items()と同等です。


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