¿Cuándo deberían usarse iteritems () en lugar de items ()?

153

¿Es legítimo usar en items()lugar de iteritems()en todos los lugares? ¿Por qué fue iteritems()eliminado de Python 3? Parece un método excelente y útil. ¿Cuál es el razonamiento detrás de esto?

Editar: para aclarar, quiero saber cuál es el idioma correcto para iterar sobre un diccionario de forma similar a un generador (un elemento a la vez, no todos en la memoria) de una manera que sea compatible con Python 2 y Python 3 ?

Martineau
fuente

Respuestas:

148

En Python 2.x: .items()devolvió una lista de pares (clave, valor). En Python 3.x, .items()es ahora un itemviewobjeto, que se comporta diferente - por lo que tiene que ser iterado sobre, o materializado ... Por lo tanto, list(dict.items())se requiere por lo que era dict.items()en Python 2.x

Python 2.7 también tiene un puerto posterior para el manejo de claves, en el sentido de que tiene viewkeys, viewitemsy viewvaluesmétodos, el ser más útil viewkeysque se comporta más como a set(que esperaría de a dict).

Ejemplo simple:

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

Le dará una lista de las claves comunes, pero nuevamente, en Python 3.x, solo use .keys()en su lugar.

Python 3.x generalmente se ha hecho para ser más "vago", mapes decir, ahora es efectivamente itertools.imap, zipes itertools.izip, etc.

Jon Clements
fuente
96

dict.iteritemsfue eliminado porque dict.itemsahora hace lo que dict.iteritemshizo en python 2.xy incluso lo mejoró un poco al convertirlo en un itemview.

Wessie
fuente
64

Las seis bibliotecas ayudan a escribir código que sea compatible con python 2.5+ y python 3. Tiene un método de iteritems que funcionará tanto en python 2 como en 3. Ejemplo:

import six

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

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

Como la documentación del diccionario para python 2 y python 3 le diría, en python 2 itemsdevuelve una lista, mientras que iteritemsdevuelve un iterador.

En python 3, itemsdevuelve una vista , que es más o menos lo mismo que un iterador.

Si está utilizando Python 2, es posible que desee usar un usuario iteritemssi se trata de diccionarios grandes y todo lo que quiere hacer es iterar sobre los elementos (no necesariamente copiarlos en una lista)

goncalopp
fuente
Entiendo que iteritemses un iterador, por eso es tan útil. Casi nunca quiero iterar sobre un diccionario como una lista. Entonces, ¿cuál es la forma correcta de iterar sobre el diccionario con algo generador como de una manera que sea compatible con Python 2 y 3?
3
@ user248237 for key in some_dictfunciona en ambos, y la 2to3herramienta se traducirá iteritems()de items()todos modos ...
Jon Clements
1
@JonClements: bastante justo, aunque siempre pensé que for k in d: d[k]es innecesariamente detallado / antipático
6

Tal como señaló @Wessie dict.iteritems, dict.iterkeysy dict.itervalues(que devuelven un iterador en Python2.x) y también dict.viewitems, dict.viewkeysy dict.viewvalues(que devuelven objetos de vista en Python2.x) se eliminaron en Python3.x

Y dict.items, dict.keysy dict.valuessolía devolver una copia de la lista del diccionario en Python2.x, ahora devuelve objetos de vista en Python3.x, pero todavía no son lo mismo que el iterador .

Si desea devolver un iterador en Python3.x, use 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
fuente
¿Qué es más eficiente cuando uno quiere hacer una búsqueda inversa? ver objetos o iterador?
Lifebalance
6

No se puede usar itemsen su lugar iteritemsen todos los lugares de Python. Por ejemplo, el siguiente código:

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 romperá si usas 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 mismo es cierto para viewitems , que está disponible en Python 3.

Además, dado que los elementos devuelven una copia de la lista de (key, value)pares del diccionario , es menos eficiente, a menos que desee crear una copia de todos modos.

En Python 2, es mejor usarlo iteritemspara la iteración. La 2to3herramienta puede reemplazarlo itemssi alguna vez decide actualizar a Python 3.

Florian Winter
fuente
0

future.utils permite la compatibilidad con python 2 y 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
fuente