Wann sollten iteritems () anstelle von items () verwendet werden?

153

Ist es legitim, items()statt iteritems()an allen Orten zu verwenden? Warum wurde iteritems()aus Python 3 entfernt? Scheint eine großartige und nützliche Methode zu sein. Was ist der Grund dafür?

Bearbeiten: Zur Verdeutlichung möchte ich wissen, was die richtige Redewendung ist, um ein Wörterbuch auf generatorähnliche Weise (jeweils ein Element, nicht alle im Speicher) auf eine Weise zu durchlaufen, die sowohl mit Python 2 als auch mit Python 3 kompatibel ist ?

Martineau
quelle

Antworten:

148

In Python 2.x - .items()gab eine Liste von (Schlüssel-, Wert-) Paaren zurück. In Python 3.x .items()handelt es sich nun um ein itemviewObjekt, das sich anders verhält - es muss also iteriert oder materialisiert werden ... Wird list(dict.items())also für das benötigt, was dict.items()in Python 2.x war.

Python 2.7 hat auch ein bisschen von einem Back-Port für die Schlüsselverwaltung, in die Sie haben viewkeys, viewitemsund viewvaluesMethoden, die nützlichste Wesen , viewkeysdie eher wie ein verhält set(was man von einem erwarten würde dict).

Einfaches Beispiel:

common_keys = list(dict_a.viewkeys() & dict_b.viewkeys())

Gibt Ihnen eine Liste der allgemeinen Schlüssel, aber auch in Python 3.x - verwenden Sie .keys()stattdessen einfach .

Python 3.x wurde im Allgemeinen als "fauler" eingestuft - dh es mapist jetzt effektiv itertools.imap, zipist itertools.izipusw.

Jon Clements
quelle
96

dict.iteritemswurde entfernt, weil dict.itemsjetzt das Ding dict.iteritemsin Python 2.x funktioniert und es sogar ein bisschen verbessert hat, indem es zu einem gemacht wurde itemview.

Wessie
quelle
64

Die Bibliothek mit sechs Funktionen hilft beim Schreiben von Code, der sowohl mit Python 2.5+ als auch mit Python 3 kompatibel ist. Sie verfügt über eine Iteritems-Methode, die sowohl in Python 2 als auch in Python 3 funktioniert. Beispiel:

import six

d = dict( foo=1, bar=2 )

for k, v in six.iteritems(d):
    print(k, v)
Dean Serenevy
quelle
9

Wie aus der Wörterbuchdokumentation für Python 2 und Python 3 hervorgeht , gibt Python 2 itemseine Liste zurück, während iteritemsein Iterator zurückgegeben wird.

Gibt in Python 3 itemseine Ansicht zurück , die einem Iterator ziemlich ähnlich ist.

Wenn Sie Python 2 verwenden, möchten Sie möglicherweise einen Benutzer verwenden, iteritemswenn Sie mit großen Wörterbüchern arbeiten und alles, was Sie tun möchten, ist, die Elemente zu durchlaufen (sie müssen nicht unbedingt in eine Liste kopiert werden).

Goncalopp
quelle
Ich verstehe, dass dies iteritemsein Iterator ist, weshalb es so nützlich ist. Ich möchte fast nie ein Wörterbuch als Liste durchlaufen. Was ist also der richtige Weg, um das Wörterbuch mit einem Generator zu iterieren, der sowohl mit Python 2 als auch mit Python 3 kompatibel ist?
3
@ user248237 for key in some_dictfunktioniert auf beides - und das 2to3Werkzeug übersetzen wird iteritems()auf items()jeden Fall ...
Jon Clements
1
@ JonClements: fair genug, obwohl ich immer dachte, for k in d: d[k]ist unnötig ausführlich / unpythonisch
6

So wie @Wessie, bemerkt dict.iteritems, dict.iterkeysund dict.itervalues(die eine Rückkehr Iterator in Python2.x) sowie dict.viewitems, dict.viewkeysund dict.viewvalues(die Rückkehr Ansicht Objekte in Python2.x) wurden alle in Python3.x entfernt

Und dict.items, dict.keysund dict.valuesverwendet, um eine Kopie der Wörterbuchliste in Python2.x zurückzugeben, geben jetzt Ansichtsobjekte in Python3.x zurück, aber sie sind immer noch nicht mit Iterator identisch .

Wenn Sie einen Iterator in Python3.x zurückgeben möchten, verwenden Sie 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
Was ist effizienter, wenn man eine inverse Suche durchführen möchte? Objekte oder Iterator anzeigen?
Lebensbalance
6

Sie können itemsstattdessen nicht iteritemsan allen Stellen in Python verwenden. Zum Beispiel der folgende Code:

class C:
  def __init__(self, a):
    self.a = a
  def __iter__(self):
    return self.a.iteritems()

>>> c = C(dict(a=1, b=2, c=3))
>>> [v for v in c]
[('a', 1), ('c', 3), ('b', 2)]

wird brechen, wenn Sie verwenden items:

class D:
  def __init__(self, a):
    self.a = a
  def __iter__(self):
    return self.a.items()

>>> d = D(dict(a=1, b=2, c=3))
>>> [v for v in d]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __iter__ returned non-iterator of type 'list'

Gleiches gilt für Ansichtselemente , die in Python 3 verfügbar sind.

Da Elemente eine Kopie der Paarliste des Wörterbuchs zurückgeben (key, value), ist dies weniger effizient, es sei denn, Sie möchten trotzdem eine Kopie erstellen.

In Python 2 ist es am besten, es iteritemsfür die Iteration zu verwenden. Das 2to3Tool kann es ersetzen, itemswenn Sie sich jemals für ein Upgrade auf Python 3 entscheiden.

Florian Winter
quelle
0

future.utils ermöglicht die Kompatibilität von Python 2 und 3

# Python 2 and 3: option 3
from future.utils import iteritems
heights = {'man': 185,'lady': 165}
for (key, value) in iteritems(heights):
    print(key,value)

>>> ('lady', 165)
>>> ('man', 185)

https://python-future.org/compatible_idioms.html

Daniel
quelle