Când ar trebui să se utilizeze iteritems() în loc de items()? (Programare, Python, Python 3.X)

utilizator248237 a intrebat.

Este legitim să se utilizeze items() în loc de iteritems() în toate locurile? De ce a fost iteritems() eliminat din Python 3? Pare a fi o metodă extraordinară și utilă. Care este raționamentul din spatele ei?

Editați: Pentru a clarifica, vreau să știu care este idiomul corect pentru a itera peste un dicționar într-un mod asemănător unui generator (câte un element la un moment dat, nu toate în memorie) într-un mod care să fie compatibil atât cu Python 2 cât și cu Python 3?

7 răspunsuri
Jon Clements

În Python 2.x – .items() a returnat o listă de perechi (cheie, valoare). În Python 3.x, .items() este acum un itemview obiect, care se comportă diferit – deci se are să fie iterat sau materializat… Așadar, list(dict.items()) este necesar pentru ceea ce era dict.items() în Python 2.x.

Python 2.7 are, de asemenea, un pic de back-port pentru manipularea cheilor, în sensul că aveți viewkeys, viewitems și viewvalues cele mai utile fiind metodele viewkeys care se comportă mai mult ca o metodă set (la care v-ați aștepta de la un dict).

Un exemplu simplu:

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

Vă va oferi o listă a cheilor comune, dar, din nou, în Python 3.x – folosiți pur și simplu .keys() în schimb.

În general, Python 3.x a fost creat pentru a fi mai „leneș” – de ex. map este acum efectiv itertools.imap, zip este itertools.izip, etc.

Comentarii

  • Nu răspunde clar la întrebarea, ce ar trebui să folosim în loc de .iteritems() ? –  > Por Jerome2606.
Wessie

dict.iteritems a fost eliminat deoarece dict.items face acum lucrul acesta dict.iteritems făcea în python 2.x și chiar l-a îmbunătățit puțin, făcându-l un itemview.

Dean Serenevy

Biblioteca șase ajută la scrierea de cod care este compatibil atât cu python 2.5+, cât și cu python 3. Are o metodă iteritems care va funcționa atât în python 2 cât și în python 3. Exemplu:

import six

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

for k, v in six.iteritems(d):
    print(k, v)

goncalopp

După cum se arată în documentația dicționarului pentru python 2 și python 3 vă spune că, în python 2 items returnează o listă, în timp ce iteritems returnează un iterator.

În python 3, items returnează un view, care este aproape la fel ca un iterator.

Dacă utilizați python 2, este posibil să doriți să utilizați iteritems dacă aveți de-a face cu dicționare mari și tot ceea ce doriți să faceți este să iterați peste elemente (nu neapărat să le copiați într-o listă).

Comentarii

  • Am înțeles că iteritems este un iterator, motiv pentru care este atât de util. Aproape niciodată nu vreau să iteratez peste un dicționar ca o listă. Deci, care este modul corect de a itera peste dicționar cu ceva generator ca într-un mod care este compatibil atât cu Python 2 cât și cu 3? – utilizator248237
  • @user248237 for key in some_dict funcționează în ambele cazuri – și 2to3 tool va traduce iteritems() la items() oricum… –  > Por Jon Clements.
  • @JonClements: destul de corect, deși am crezut întotdeauna că for k in d: d[k] este inutil de verbos / nepitit – user248237
YaOzI

Exact așa cum a remarcat @Wessie, dict.iteritems, dict.iterkeys și dict.itervalues (care returnează un iterator în Python2.x), precum și dict.viewitems, dict.viewkeys și dict.viewvalues (care returnează obiecte de vizualizare în Python2.x) au fost toate eliminate în Python3.x

Și dict.items, dict.keys și dict.values utilizate pentru a returna un copie a listei dicționarului în Python2.x acum returnează obiecte de vizualizare în Python3.x, dar acestea nu sunt încă la fel ca iterator.

Dacă doriți să returnați un iterator în Python3.x, utilizați 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'>

Comentarii

  • Ce este mai eficient atunci când se dorește să se facă o căutare inversă? obiecte de vizualizare sau iterator? –  > Por lifebalance.
Florian Winter

Nu puteți utiliza items în loc de iteritems în toate locurile în Python. De exemplu, următorul cod:

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)]

se va întrerupe dacă folosiți 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'

Același lucru este valabil și pentru viewitems, care este disponibil în Python 3.

De asemenea, deoarece items returnează o copie a listei de elemente din dicționar (key, value) perechi, este mai puțin eficient, cu excepția cazului în care doriți să creați oricum o copie.

În Python 2, cel mai bine este să folosiți iteritems pentru iterație. Adresa 2to3 îl poate înlocui cu items dacă vă decideți vreodată să faceți upgrade la Python 3.

Daniel

future.utils permite compatibilitatea cu python 2 și 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)

Consultați acest link: https://python-future.org/compatible_idioms.html