Kiedy powinno się używać iteritems () zamiast items ()?

153

Czy używanie items()zamiast iteritems()wszędzie jest uzasadnione ? Dlaczego został iteritems()usunięty z Pythona 3? Wydaje się świetną i przydatną metodą. Jaki jest tego powód?

Edycja: Aby wyjaśnić, chcę wiedzieć, jaki jest poprawny idiom do iteracji po słowniku w sposób podobny do generatora (jeden element na raz, nie wszystkie do pamięci) w sposób zgodny zarówno z Pythonem 2, jak i Pythonem 3 ?

martineau
źródło

Odpowiedzi:

148

W Pythonie 2.x - .items()zwróciło listę par (klucz, wartość). W Pythonie 3.x .items()jest teraz itemviewobiektem, który zachowuje się inaczej - więc musi być iterowany lub zmaterializowany ... Tak więc list(dict.items())jest wymagany do tego, co było dict.items()w Pythonie 2.x.

Python 2.7 ma także trochę back-port dla klucza obchodzenia się, że masz viewkeys, viewitemsa viewvaluesmetody, najbardziej przydatne istota viewkeys, która zachowuje się bardziej jak set(co można oczekiwać od A dict).

Prosty przykład:

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

Wyświetli listę typowych kluczy, ale znowu, w Pythonie 3.x - po prostu użyj .keys()zamiast tego.

Python 3.x jest generalnie bardziej „leniwy” - mapto znaczy jest teraz efektywny itertools.imap, zipjest itertools.izipitd.

Jon Clements
źródło
96

dict.iteritemszostał usunięty, ponieważ dict.itemsteraz robi to dict.iteritemssamo w Pythonie 2.x, a nawet ulepszył go nieco, zmieniając plik itemview.

Wessie
źródło
64

Sześć bibliotek pomaga w pisaniu kodu, który jest kompatybilny zarówno z Pythonem 2.5+, jak i Pythonem 3. Posiada metodę iteritems, która będzie działać zarówno w Pythonie 2, jak i 3. Przykład:

import six

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

for k, v in six.iteritems(d):
    print(k, v)
Dean Serenevy
źródło
9

Jak powie Ci dokumentacja słownika dla pythona 2 i pythona 3 , w pythonie 2 itemszwraca listę, a iteritemszwraca iterator.

W Pythonie 3 itemszwraca widok , który jest prawie taki sam jak iterator.

Jeśli używasz Pythona 2, możesz chcieć user, iteritemsjeśli masz do czynienia z dużymi słownikami i wszystko, co chcesz zrobić, to iterować po elementach (niekoniecznie kopiować je na listę)

goncalopp
źródło
Rozumiem, że iteritemsto iterator, dlatego jest tak przydatny. Prawie nigdy nie chcę przeglądać słownika jako listy. Więc jaki jest właściwy sposób iteracji słownika z generatorem w sposób zgodny zarówno z Pythonem 2, jak i 3?
3
@ user248237 for key in some_dictdziała na obu - a 2to3narzędzie i tak przetłumaczy iteritems()na items()...
Jon Clements
1
@JonClements: w porządku, chociaż zawsze uważałem, że for k in d: d[k]jest niepotrzebnie gadatliwy / niepytoniczny
6

Podobnie jak zauważyć @Wessie, dict.iteritems, dict.iterkeysi dict.itervalues(które zwracają iterację w Python2.x), jak również dict.viewitems, dict.viewkeysoraz dict.viewvalues(co powrót widok obiektów w Python2.x) były usunięte w Python3.x

A dict.items, dict.keysi dict.valuesużywany do zwracania kopię listy słownika w Python2.x teraz powrócić Wyświetlanie obiektów w Python3.x, ale nie są one jeszcze tak samo jak iteratora .

Jeśli chcesz zwrócić iterator w Python3.x, użyj 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
źródło
Co jest bardziej wydajne, gdy chce się przeprowadzić wyszukiwanie odwrotne? przeglądać obiekty czy iterator?
Lifebalance
6

Nie możesz używać itemszamiast tego iteritemswe wszystkich miejscach w Pythonie. Na przykład następujący kod:

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

zepsuje się, jeśli użyjesz 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'

To samo dotyczy viewitems , które jest dostępne w Pythonie 3.

Ponadto, ponieważ elementy zwracają kopię listy (key, value)par ze słownika , jest to mniej wydajne, chyba że i tak chcesz utworzyć kopię.

W Pythonie 2 najlepiej używać go iteritemsdo iteracji. 2to3Narzędzie może zastąpić go items, jeśli kiedykolwiek zdecydujesz się na uaktualnienie do Python 3.

Florian Winter
źródło
0

future.utils zapewnia zgodność z Pythonem 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)

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

Daniel
źródło