python update Iterando sobre dicionários usando loops 'for'




transformar lista em dicionario python (9)

Você pode verificar a implementação do dicttype do CPython no GitHub. Esta é a assinatura do método que implementa o dict iterator:

_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
             PyObject **pvalue, Py_hash_t *phash)

CPython dictobject.c

Estou um pouco confuso com o seguinte código:

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:
    print key, 'corresponds to', d[key]

O que eu não entendo é a parte key . Como o Python reconhece que precisa apenas ler a chave do dicionário? A key é uma palavra especial em Python? Ou é simplesmente uma variável?


Para iterar sobre chaves, é mais lento, mas é melhor usar my_dict.keys() . Se você tentou fazer algo assim:

for key in my_dict:
    my_dict[key+"-1"] = my_dict[key]-1

ele criaria um erro de tempo de execução porque você está alterando as chaves enquanto o programa está sendo executado. Se você está absolutamente determinado a reduzir o tempo, use a for key in my_dict way, mas você foi avisado;).


Não é que a chave seja uma palavra especial, mas os dicionários implementam o protocolo do iterador. Você poderia fazer isso em sua classe, por exemplo, ver esta pergunta sobre como construir iteradores de classe.

No caso de dicionários, é implementado no nível C. Os detalhes estão disponíveis no PEP 234 . Em particular, a seção intitulada "Dicionário Iteradores":

  • Os dicionários implementam um slot tp_iter que retorna um iterador eficiente que itera sobre as chaves do dicionário. [...] isso significa que podemos escrever

    for k in dict: ...
    

    o que é equivalente, mas muito mais rápido do que

    for k in dict.keys(): ...
    

    contanto que a restrição de modificações no dicionário (seja pelo loop ou por outro thread) não seja violada.

  • Adicione métodos a dicionários que retornam diferentes tipos de iteradores explicitamente:

    for key in dict.iterkeys(): ...
    
    for value in dict.itervalues(): ...
    
    for key, value in dict.iteritems(): ...
    

    Isso significa que for x in dict é um atalho for x in dict.iterkeys() .


Eu tenho um caso de uso onde eu tenho que percorrer o dict para obter a chave, valor par, também o índice indicando onde estou. É assim que eu faço:

d = {'x': 1, 'y': 2, 'z': 3} 
for i, (key, value) in enumerate(d.items()):
   print(i, key, value)

Note que os parênteses em torno da chave, o valor é importante, sem os parênteses, você obtém um valor ValueError "não é suficiente para descompactar".



Quando você faz uma iteração através de dicionários usando a sintaxe for .. in .. , sempre itera sobre as teclas (os valores são acessíveis usando o dictionary[key] ).

Para iterar sobre pares de valores-chave, use for k,v in s.iteritems() .


key é simplesmente uma variável.

Para Python2.X :

d = {'x': 1, 'y': 2, 'z': 3} 
for my_var in d:
    print my_var, 'corresponds to', d[my_var]

... ou melhor,

d = {'x': 1, 'y': 2, 'z': 3} 
for the_key, the_value in d.iteritems():
    print the_key, 'corresponds to', the_value

Para Python3.X :

d = {'x': 1, 'y': 2, 'z': 3} 
for the_key, the_value in d.items():
    print(the_key, 'corresponds to', the_value)

Você pode usar isto:

for key,val in d.items():
    print key, 'is the key for ', val

Iterando sobre dicionários usando loops 'for'

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:
    ...

Como o Python reconhece que precisa apenas ler a chave do dicionário? A chave é uma palavra especial em Python? Ou é simplesmente uma variável?

Não é apenas for loops. A palavra importante aqui é "iterar".

Um dicionário é um mapeamento de chaves para valores:

d = {'x': 1, 'y': 2, 'z': 3} 

Sempre que fazemos uma iteração, iteramos as teclas. A key nome de variável destina-se apenas a ser descritiva - e é bastante adequada para o propósito.

Isso acontece em uma compreensão da lista:

>>> [k for k in d]
['x', 'y', 'z']

Isso acontece quando passamos o dicionário para listar (ou qualquer outro objeto de tipo de coleção):

>>> list(d)
['x', 'y', 'z']

A maneira que o Python é iterado é, em um contexto onde ele precisa, ele chama o método __iter__ do objeto (neste caso o dicionário) que retorna um iterador (neste caso, um objeto keyiterator):

>>> d.__iter__()
<dict_keyiterator object at 0x7fb1747bee08>

Nós não devemos usar esses métodos especiais, em vez disso, usar a respectiva função interna para chamá-lo, iter :

>>> key_iterator = iter(d)
>>> key_iterator
<dict_keyiterator object at 0x7fb172fa9188>

Iteradores têm um método __next__ - mas nós o chamamos com a função interna, a next :

>>> next(key_iterator)
'x'
>>> next(key_iterator)
'y'
>>> next(key_iterator)
'z'
>>> next(key_iterator)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Quando um iterador está esgotado, ele aumenta o StopIteration . É assim que o Python sabe como sair de um loop for , ou uma compreensão de lista, ou uma expressão de gerador, ou qualquer outro contexto iterativo. Uma vez que um iterador aumenta o StopIteration ele sempre aumentará - se você quiser iterar novamente, precisará de um novo.

>>> list(key_iterator)
[]
>>> new_key_iterator = iter(d)
>>> list(new_key_iterator)
['x', 'y', 'z']

Voltando aos ditos

Nós vimos ditadores interagindo em muitos contextos. O que temos visto é que, a qualquer momento que fazemos uma iteração, recebemos as chaves. De volta ao exemplo original:

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:

Se mudarmos o nome da variável, ainda assim obteremos as chaves. Vamos tentar:

>>> for each_key in d:
...     print(each_key, '=>', d[each_key])
... 
x => 1
y => 2
z => 3

Se queremos iterar sobre os valores, precisamos usar o método .values dos .values , ou ambos juntos, .items :

>>> list(d.values())
[1, 2, 3]
>>> list(d.items())
[('x', 1), ('y', 2), ('z', 3)]

No exemplo dado, seria mais eficiente iterar sobre os itens como este:

for a_key, corresponding_value in d.items():
    print(a_key, corresponding_value)

Mas para fins acadêmicos, o exemplo da pergunta é bom.







dictionary