Dicionário Python: as chaves () e os valores () sempre estão na mesma ordem?

312

Parece que as listas retornadas keys()e os values()métodos de um dicionário são sempre um mapeamento 1 para 1 (assumindo que o dicionário não seja alterado entre chamar os 2 métodos).

Por exemplo:

>>> d = {'one':1, 'two': 2, 'three': 3}
>>> k, v = d.keys(), d.values()
>>> for i in range(len(k)):
    print d[k[i]] == v[i]

True
True
True

Se você não alterar o dicionário entre chamadas keys()e chamadas values(), é errado assumir que o loop for acima sempre imprimirá True? Não encontrei nenhuma documentação confirmando isso.

Jason Coon
fonte
1
No CPython 3.7 (e superior, presumivelmente), você pode confiar na ordem de iteração de uma ordem de inserção de dicionário correspondente. mail.python.org/pipermail/python-dev/2017-December/151283.html
BallpointBen
O @BallpointBen está no CPython 3.6 e posterior e em todas as outras implementações em Python começando com Python 3.7
Boris

Respostas:

353

Encontrou isto:

Se items(), keys(), values(), iteritems(), iterkeys(), e itervalues()são chamados sem modificações intervenientes para o dicionário, as listas corresponderá diretamente.

Na documentação 2.x e documentação 3.x .

nosklo
fonte
5
aparentemente a declaração na documentação 3.x é mais clara: "a ordem dos itens corresponderá diretamente"
Shaohua Li
4
Este texto está ausente na documentação 3.7. Só posso supor que é porque "Dict mantém a ordem de inserção" em 3.7: mail.python.org/pipermail/python-dev/2017-December/151283.html
EliadL
80

Sim, o que você observou é realmente uma propriedade garantida - chaves (), valores () e itens () retornam listas em ordem congruente, se o ditado não for alterado. iterkeys () & c também iteram na mesma ordem que as listas correspondentes.

Alex Martelli
fonte
1
No entanto, caso a lista seja alterada, o Pandas dataframeoferece uma alternativa em que os itens podem ser atualizados ou excluídos, e a ordem e os locais de índice dos itens em uma estrutura semelhante a um ditado permanecem fixos.
Ville
48

Sim, é garantido no python 2.x :

Se as visualizações de chaves, valores e itens forem iteradas sem modificações no dicionário, a ordem dos itens corresponderá diretamente.

Bjorn
fonte
6

Boas referências aos documentos. Veja como você pode garantir o pedido, independentemente da documentação / implementação:

k, v = zip(*d.iteritems())
Sassa NF
fonte
1
No python3.x, use dict.items ()
Good Will
4

De acordo com http://docs.python.org/dev/py3k/library/stdtypes.html#dictionary-view-objects , os métodos keys (), values ​​() e items () de um dict retornarão iteradores correspondentes cujas ordens corresponde. No entanto, não consigo encontrar uma referência à documentação oficial do python 2.x para a mesma coisa.

Até onde eu sei, a resposta é sim, mas apenas no python 3.0+

sykora
fonte
4

Pelo que vale a pena, algum código de produção usado pesado que eu escrevi é baseado nessa suposição e nunca tive problemas com isso. Eu sei que isso não é verdade :-)

Se você não quiser correr o risco, eu usaria iteritems (), se puder.

for key, value in myDictionary.iteritems():
    print key, value
Koen Bok
fonte
-2

Não fiquei satisfeito com essas respostas, pois queria garantir que os valores exportados tivessem a mesma ordem, mesmo ao usar ditados diferentes.

Aqui você especifica a ordem das chaves antecipadamente, os valores retornados sempre terão a mesma ordem, mesmo que o ditado mude, ou use um ditado diferente.

keys = dict1.keys()
ordered_keys1 = [dict1[cur_key] for cur_key in keys]
ordered_keys2 = [dict2[cur_key] for cur_key in keys]
jlansey
fonte