176 votes

Quand faut-il utiliser iteritems() au lieu de items() ?

Est-il légitime d'utiliser items() au lieu de iteritems() en tous lieux ? Pourquoi la iteritems() supprimé de Python 3 ? Cela semble être une méthode formidable et utile. Quel est le raisonnement derrière cela ?

Edit : Pour clarifier, je veux savoir quel est le bon idiome pour itérer sur un dictionnaire à la manière d'un générateur (un élément à la fois, pas tous en mémoire) d'une manière qui soit compatible avec Python 2 et Python 3 ?

7voto

Florian Winter Points 61

Vous ne pouvez pas utiliser items au lieu de iteritems en tous lieux dans Python. Par exemple, le code suivant :

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 brisera si vous utilisez 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'

Il en va de même pour voir les articles qui est disponible dans Python 3.

En outre, étant donné que articles renvoie une copie de la liste des éléments suivants du dictionnaire (key, value) paires, c'est moins efficace, à moins que vous ne vouliez de toute façon créer une copie.

En Python 2, il est préférable d'utiliser iteritems pour l'itération. Le site 2to3 peut le remplacer par items si vous décidez un jour de passer à Python 3.

6voto

Daniel Points 862

future.utils permet d'assurer la compatibilité avec python 2 et 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)

Voir ce lien : https://python-future.org/compatible_idioms.html

1voto

ShadowRanger Points 44

Si, pour une raison ou une autre, quelqu'un a toujours besoin de le faire et ne veut pas utiliser une bibliothèque de compatibilité, une approche simple consiste à créer une appelable de haut niveau qui appelle la bonne bibliothèque par version :

from operator import methodcaller
try:
    {}.viewitems()
except AttributeError:
    # Py3, use items
    viewitems = methodcaller('items')
else:
    viewitems = methodcaller('viewitems')

mydict = {...}
for k, v in viewitems(mydict):
    ...

Le comportement sera identique sur 2.7 et 3+ (pas de copie, toujours une vue en direct). Vous pouvez changer toutes les références en view de view a iter pour prendre en charge les versions antérieures à la version 2.7 de Python, bien que le comportement soit subtilement différent dans certains cas (les vues sont itératives). ble mais pas les itera tor vous pouvez appeler next sur un itérateur, mais pas sur un itérable non itérateur).

En pratique, cependant :

  1. À ce stade, Py2 est EOL, donc il suffit d'écrire pour Py3, et
  2. Si vous devez supporter les deux, écrivez de la manière la plus portative possible pour Py2 (avec tous les __future__ importations, explicites u y b préfixes pour les littéraux de type texte ou octet, utilisation de io.open pour remplacer open etc.) et utiliser 2to3 pour les petites choses que vous ne pouvez pas écrire directement de manière portative.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X