Quando iteritems () devem ser usados ​​em vez de itens ()?


153

É legítimo usar em items()vez de iteritems()em todos os lugares? Por que foi iteritems()removido do Python 3? Parece um método fantástico e útil. Qual é o raciocínio por trás disso?

Editar: para esclarecer, quero saber qual é o idioma correto para iterar sobre um dicionário de maneira semelhante a um gerador (um item de cada vez, não todos na memória) de uma forma compatível com o Python 2 e o Python 3 ?

Respostas:


148

No Python 2.x - .items()retornou uma lista de pares (chave, valor). No Python 3.x, .items()agora é um itemviewobjeto que se comporta de maneira diferente - portanto, ele precisa ser iterado ou materializado ... Portanto, list(dict.items())é necessário para o que estava dict.items()no Python 2.x.

Python 2.7 também tem um pouco de back-porta para a manipulação chave, em que você tem viewkeys, viewitemse viewvaluesmétodos, o ser mais útil viewkeysque se comporta mais como um set(que você esperaria de um dict).

Exemplo simples:

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

Fornecerá uma lista das chaves comuns, mas, novamente, no Python 3.x - basta usar .keys().

O Python 3.x geralmente é considerado mais "preguiçoso" - ou mapseja, agora é efetivamente itertools.imap, zipé itertools.izipetc.


96

dict.iteritemsfoi removido porque dict.itemsagora faz a coisadict.iteritems no python 2.xe até melhorou um pouco, tornando-o um itemview.


64

A biblioteca seis ajuda a escrever um código compatível com o python 2.5+ e o python 3. Ele possui um método de iteritems que funcionará no python 2 e 3. Exemplo:

import six

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

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

9

Como a documentação do dicionário para python 2 e python 3 diria, no python 2 itemsretorna uma lista, enquanto iteritemsretorna um iterador.

No python 3, itemsretorna uma visualização , que é praticamente a mesma de um iterador.

Se você estiver usando python 2, convém usar o usuário iteritemsse estiver lidando com dicionários grandes e tudo o que você deseja fazer é iterar nos itens (não necessariamente copiá-los para uma lista)


Entendo que iteritemsé um iterador, e é por isso que é tão útil. Eu quase nunca quero repetir um dicionário como uma lista. Então, qual é a maneira correta de iterar no dicionário com algo como um gerador compatível com o Python 2 e 3?

3
@ user248237 for key in some_dictfunciona em ambos - e a 2to3ferramenta será traduzida iteritems()para items()qualquer forma ...
Jon Clements

1
@JonClements: justo o suficiente, embora eu sempre pensei que for k in d: d[k]é desnecessariamente verbose / unpythonic

6

Assim como @Wessie observou, dict.iteritems, dict.iterkeyse dict.itervalues(que retornar um iterador em python2.x), bem como dict.viewitems, dict.viewkeyse dict.viewvalues(que retornam ver objetos em python2.x) foram todas removidas em Python3.x

E dict.items, dict.keyse dict.valuesusado para retornar uma cópia da lista do dicionário em python2.x agora retornar ver objetos em Python3.x, mas eles ainda não são o mesmo que iterator .

Se você deseja retornar um iterador no 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'>

Qual é mais eficiente quando se deseja fazer uma pesquisa inversa? visualizar objetos ou iterador?
lifebalance

6

Você não pode usar itemsem vez iteritemsde todos os lugares em Python. Por exemplo, o seguinte 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)]

irá quebrar se você usar 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'

O mesmo vale para os itens de exibição , disponíveis no Python 3.

Além disso, como os itens retornam uma cópia da lista de (key, value)pares do dicionário , é menos eficiente, a menos que você deseje criar uma cópia de qualquer maneira.

No Python 2, é melhor usar iteritemspara iteração. A 2to3ferramenta pode substituí-lo itemsse você decidir atualizar para o Python 3.


0

future.utils permite compatibilidade com 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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.