Quando dovrebbe essere usato iteritems () invece di items ()?


153

È legittimo utilizzare items()invece che iteritems()in tutti i luoghi? Perché è stato iteritems()rimosso da Python 3? Sembra un metodo formidabile e utile. Qual è il ragionamento alla base?

Modifica: Per chiarire, voglio sapere qual è il linguaggio corretto per iterare su un dizionario in modo simile a un generatore (un elemento alla volta, non tutto in memoria) in un modo compatibile con Python 2 e Python 3 ?

Risposte:


148

In Python 2.x: .items()restituito un elenco di coppie (chiave, valore). In Python 3.x, .items()ora è un itemviewoggetto, che si comporta in modo diverso - quindi deve essere ripetuto o materializzato ... Quindi, list(dict.items())è necessario per ciò che era dict.items()in Python 2.x.

Python 2.7 ha anche un po 'di back-port per la gestione delle chiavi, in quanto hai viewkeys, viewitemse viewvaluesmetodi, l'essere più utile viewkeysche si comporta più come un set(che ti aspetteresti da un dict).

Esempio semplice:

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

Ti fornirà un elenco delle chiavi comuni, ma di nuovo, in Python 3.x: basta usare .keys()invece.

Python 3.x è stato generalmente reso più "pigro" - cioè mapora è efficace itertools.imap, zipè itertools.izip, ecc.


96

dict.iteritemsè stato rimosso perché dict.itemsora fa ciò che ha dict.iteritemsfatto in Python 2.x e lo ha persino migliorato un po 'rendendolo un itemview.


64

La libreria sei aiuta a scrivere codice compatibile sia con Python 2.5+ sia con Python 3. Ha un metodo iteritems che funzionerà sia in Python 2 che 3. Esempio:

import six

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

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

9

Come direbbe la documentazione del dizionario per Python 2 e Python 3 , in Python 2 itemsrestituisce un elenco, mentre iteritemsrestituisce un iteratore.

In Python 3, itemsrestituisce una vista , che è praticamente la stessa di un iteratore.

Se stai usando Python 2, potresti voler essere utente iteritemsse hai a che fare con dizionari di grandi dimensioni e tutto ciò che vuoi fare è scorrere gli elementi (non necessariamente copiarli in un elenco)


Capisco che iteritemsè un iteratore, motivo per cui è così utile. Non voglio quasi mai scorrere su un dizionario come elenco. Quindi qual è il modo corretto di scorrere il dizionario con qualcosa di simile a un generatore in un modo compatibile con Python 2 e 3?

3
@ user248237 for key in some_dictfunziona sia - e lo 2to3strumento si tradurrà iteritems()per items()comunque ...
Jon Clements

1
@JonClements: abbastanza giusto, anche se ho sempre pensato che for k in d: d[k]fosse inutilmente prolisso / non pitonico

6

Proprio come ha notato @Wessie dict.iteritems, dict.iterkeyse dict.itervalues(che restituiscono un iteratore in Python2.x) nonché dict.viewitems, dict.viewkeyse dict.viewvalues(che restituiscono oggetti vista in Python2.x) sono stati tutti rimossi in Python3.x

E dict.items, dict.keyse dict.valuesusato per restituire una copia dell'elenco del dizionario in Python2.x ora restituisce gli oggetti vista in Python3.x, ma non sono ancora gli stessi dell'iteratore .

Se si desidera restituire un iteratore in Python3.x, utilizzare 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'>

Qual è più efficiente quando si vuole fare una ricerca inversa? visualizzare oggetti o iteratore?
lifebalance

6

Non è possibile utilizzare itemsinvece iteritemsin tutti i luoghi in Python. Ad esempio, il seguente codice:

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

si romperà se si utilizza 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'

Lo stesso vale per viewitems , disponibile in Python 3.

Inoltre, poiché gli articoli restituiscono una copia dell'elenco di (key, value)coppie del dizionario , è meno efficiente, a meno che tu non voglia comunque crearne una copia.

In Python 2, è meglio usarlo iteritemsper l'iterazione. Lo 2to3strumento può sostituirlo con itemsse decidi di aggiornare a Python 3.


0

future.utils consente la compatibilità con python 2 e 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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.