Was ist der Unterschied zwischen dict.items () und dict.iteritems () in Python2?

705

Gibt es anwendbare Unterschiede zwischen dict.items()und dict.iteritems()?

Aus den Python-Dokumenten :

dict.items(): Gibt eine Kopie der Wörterbuchliste der (Schlüssel-, Wert-) Paare zurück.

dict.iteritems(): Gibt einen Iterator über die Paare des Wörterbuchs (Schlüssel, Wert) zurück.

Wenn ich den folgenden Code ausführe, scheint jeder einen Verweis auf dasselbe Objekt zurückzugeben. Gibt es subtile Unterschiede, die mir fehlen?

#!/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'   

Ausgabe:

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
der Wolf
quelle
41
Es ist im Grunde ein Unterschied, wie sie berechnet werden. items()Erstellt die Elemente auf einmal und gibt eine Liste zurück. iteritems()Gibt einen Generator zurück - Ein Generator ist ein Objekt, das jedes Mal, wenn next()es aufgerufen wird, jeweils ein Element "erstellt" .
Joel Cornett
9
In Ihrem speziellen Fall d[k] is vwürde immer True zurückgegeben, da Python ein Array von Ganzzahlobjekten für alle Ganzzahlen zwischen -5 und 256 speichert : docs.python.org/2/c-api/int.html Wenn Sie ein Int in diesem Bereich erstellen Eigentlich nur einen Verweis auf das vorhandene Objekt >> a = 2; b = 2 >> a is b True>> a = 1234567890; b = 1234567890 >> a is b False
zurückbekommen
3
@the_wolf Ich denke, es wäre besser, die Python-Version des Dokuments hinzuzufügen, auf das Sie sich in der Frage beziehen.
Lorenzo Belli
2
Wurde in Python 3 iteritems()geändert iter()? Der obige Dokumentationslink scheint nicht mit dieser Antwort übereinzustimmen.
Gabriel Staples
3
Nicht genau, @GabrielStaples. iteritems () wird aus den Wörterbüchern Python 3 entfernt und kann nicht ersetzt werden. Für den gleichen Effekt verwenden Sie jedoch iter (). zB iter (dict.items ()). Siehe Seite 469: python.org/dev/peps/pep-0469
Zim

Antworten:

863

Es ist Teil einer Evolution.

Ursprünglich hat Python items()eine echte Liste von Tupeln erstellt und diese zurückgegeben. Das könnte möglicherweise viel zusätzlichen Speicherplatz beanspruchen.

Dann wurden Generatoren in die Sprache im Allgemeinen eingeführt, und diese Methode wurde als Iterator-Generator-Methode mit dem Namen neu implementiert iteritems(). Das Original bleibt aus Gründen der Abwärtskompatibilität erhalten.

Eine der Änderungen von Python 3 besteht darin, dass items()jetzt Iteratoren zurückgegeben werden und eine Liste nie vollständig erstellt wird. Die iteritems()Methode ist auch weg, da items()in Python 3 wie viewitems()in Python 2.7 funktioniert .

Keith
quelle
159
Beachten Sie, dass Sie einen Schritt in der Evolution verpasst haben: Das Py3-Verhalten ist nicht dasselbe wie iteritems(). Tatsächlich wird ein vollständiges Sequenzprotokollobjekt erstellt, das auch Änderungen am Diktat widerspiegelt (und vom Diktat selbst und nicht von einer redundanten Liste unterstützt wird) - es wurde auf 2.7 as zurückportiert viewitems().
lvc
3
Ich würde gerne mehr darüber erfahren, aber mein Google-Fu versagt mir. Könnte mich jemand auf Dokumentationen, Artikel oder Quellen verweisen, die mir helfen würden, dies besser zu verstehen? @lvc?
Eintopf
10
@Stew die Änderung ist in PEP 3106 beschrieben und es gibt ein bisschen mehr in dem, was in Python 3.0 neu ist
Tadhg McDonald-Jensen
1
Tut mir leid, dass ich auf diese alte Frage eingegangen bin, aber verstehe ich richtig, dass dies in Python 2.x iteritems()immer vorzuziehen istitems() ?
RubenGeert
2
@RubenGeert Meistens spielt es keine Rolle. Für wirklich große Diktate könnte es vorzuziehen sein.
Keith
95

dict.items()Gibt eine Liste von 2-Tupeln ( [(key, value), (key, value), ...]) zurück, während dict.iteritems()ein Generator 2-Tupel liefert. Ersteres benötigt anfangs mehr Platz und Zeit, aber der Zugriff auf jedes Element ist schnell, während das zweite anfangs weniger Platz und Zeit benötigt, aber etwas mehr Zeit für die Generierung jedes Elements.

Ignacio Vazquez-Abrams
quelle
9
Warum würden Sie erwarten, dass sie anders sind?
Ignacio Vazquez-Abrams
3
Die "Kopie" in den Dokumenten bedeutet nicht, dass die Elemente kopiert werden (wenn Sie das möchten, verwenden Sie copy.deepcopy). Dies bedeutet, dass es sich um eine Kopie der Wörterbuchelemente handelt: Wenn Sie dies tun items = dct.items()und dann dctdurch Hinzufügen / Löschen von Schlüsseln oder ändern dct[k] = other_v, itemsbleibt dies gleich.
Dougal
4
Nichts in Python ist jemals eine tiefe Kopie, es sei denn, dies ist ausdrücklich als solches dokumentiert.
Karl Knechtel
1
@ IgnacioVazquez-Abrams - In Bezug auf "mehr Raum und Zeit": Bei welcher Größe des Wörterbuchs beginnen sie eine Rolle zu spielen. Angenommen, ich habe ein "großes" Wörterbuch, {1:'one', 2:'two', ... }über das ich auf einem Webserver iterieren und die Ergebnisse rendern möchte. In welchem ​​Umfang sollte ich mir Gedanken über die Auswahl von .items()vs .iteritems()für Python 2.7 machen?
Benutzer
1
@buffer: Nicht wirklich sicher. Meine Schätzung wäre 15-20 Artikel, aber ich habe das nicht getestet.
Ignacio Vazquez-Abrams
64

In Py2.x.

Die Befehle dict.items(), dict.keys()und dict.values()geben eine Kopie der Wörterbuchliste von (k, v)Paar, Schlüssel und Werte. Dies kann viel Speicherplatz beanspruchen, wenn die kopierte Liste sehr groß ist.

Die Befehle dict.iteritems(), dict.iterkeys()und dict.itervalues()geben ein Iterator über das (k, v)Wörterbuchpaar, Schlüssel und Werte.

Die Befehle dict.viewitems(), dict.viewkeys()und dict.viewvalues()geben die Ansicht Objekte , die das Wörterbuch der Änderungen reflektieren kann. (Wenn Sie also delein Element oder ein (k,v)Paar zum Wörterbuch hinzufügen , kann sich das Ansichtsobjekt gleichzeitig automatisch ändern.)

$ 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'>

Während in Py3.x.

In Py3.x, sind die Dinge sauber, da es nur gibt dict.items(), dict.keys()und zur dict.values()Verfügung, die die Rückansicht Objekte als nur dict.viewitems()in Py2.x tat.

Aber

Wie @lvc bemerkt hat, ist das Ansichtsobjekt nicht dasselbe wie der Iterator . Wenn Sie also einen Iterator in Py3.x zurückgeben möchten, können Sie Folgendes verwenden 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'>
YaOzI
quelle
34

Sie haben gefragt: "Gibt es anwendbare Unterschiede zwischen dict.items () und dict.iteritems ()?"

Dies kann helfen (für Python 2.x):

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

Sie können sehen, dass d.items()eine Liste von Tupeln der Schlüssel- und Wertepaare und d.iteritems()ein Wörterbuch-Elementiterator zurückgegeben werden.

Als Liste ist d.items () Slice-fähig:

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

Hätte aber keine __iter__Methode:

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

Als Iterator kann d.iteritems () nicht geschnitten werden :

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

Hat aber __iter__:

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

Die Artikel selbst sind also gleich - der Container, der die Artikel liefert, ist unterschiedlich. Eine ist eine Liste, die andere ein Iterator (abhängig von der Python-Version ...)

Die anwendbaren Unterschiede zwischen dict.items () und dict.iteritems () sind also dieselben wie die anwendbaren Unterschiede zwischen einer Liste und einem Iterator.

dawg
quelle
15

dict.items()Liste der Tupel zurückgeben und dict.iteritems()Iteratorobjekt des Tupels im Wörterbuch als zurückgeben (key,value). Die Tupel sind gleich, aber der Container ist unterschiedlich.

dict.items()kopiert grundsätzlich alle Wörterbücher in die Liste. Versuchen Sie, den folgenden Code zu verwenden, um die Ausführungszeiten von dict.items()und zu vergleichen dict.iteritems(). Sie werden den Unterschied sehen.

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

Ausgabe in meiner Maschine:

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

Dies zeigt deutlich, dass dies dictionary.iteritems()viel effizienter ist.

Prabhu
quelle
4

Wenn Sie haben

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

In Python 2 , dict.items()Kopien jedes Tupel und gibt die Liste von Tupeln im Wörterbuch dh [(key1,value1), (key2,value2), ...]. Implikationen sind, dass das gesamte Wörterbuch in eine neue Liste mit Tupeln kopiert wird

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

dict.iteritems()Gibt den Iterator für Wörterbuchelemente zurück. Der Wert des zurückgegebenen Elements ist ebenfalls derselbe, dh (key1,value1), (key2,value2), ...dies ist keine Liste. Dies ist nur ein Iteratorobjekt für Wörterbuchelemente. Das bedeutet weniger Speicherbedarf (50% weniger).

  • Listen als veränderbare Schnappschüsse: d.items() -> list(d.items())
  • Iteratorobjekte: d.iteritems() -> iter(d.items())

Die Tupel sind die gleichen. Sie haben jeweils Tupel verglichen, damit Sie gleich sind.

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

In Python 3 , dict.items()iterator kehrt Objekt. dict.iteritems () wird entfernt, sodass kein Problem mehr auftritt.

Hary Bakta
quelle
4

dict.iteritemsist in Python3.x verschwunden. Verwenden Sie also iter(dict.items()), um die gleiche Ausgabe- und Speicherzuordnung zu erhalten

Tessaracter
quelle
1

Wenn Sie die Elementpaare eines Wörterbuchs iterieren möchten, das sowohl mit Python 2 als auch mit Python 3 funktioniert, versuchen Sie Folgendes:

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

Verwenden Sie es so:

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

dict.iteritems(): gibt Ihnen einen Iterator. Sie können den Iterator in anderen Mustern außerhalb der Schleife verwenden.

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')
Ethplumber
quelle
-5

dict.iteritems () in Python 2 entspricht dict.items () in Python 3.

user128364
quelle
2
Das ist falsch. Der Unterschied wurde bereits in früheren Antworten erklärt.
Vaultah