Słownik Pythona: czy klucze () i wartości () są zawsze tej samej kolejności?

312

Wygląda na to, że listy zwracane przez keys()i values()metody słownika są zawsze mapowaniem 1 na 1 (zakładając, że słownik nie jest zmieniany między wywołaniem 2 metod).

Na przykład:

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

Jeśli nie zmienisz słownika między dzwonieniem keys()a dzwonieniem values(), czy błędem jest założenie, że powyższa pętla for zawsze będzie wyświetlać True? Nie mogłem znaleźć żadnej dokumentacji potwierdzającej to.

Jason Coon
źródło
1
W CPython 3.7 (i więcej, przypuszczalnie) możesz polegać na kolejności iteracji słownika odpowiadającej kolejności wstawiania. mail.python.org/pipermail/python-dev/2017-December/151283.html
BallpointBen
@BallpointBen jest w CPython 3.6 i nowszych wersjach oraz we wszystkich innych implementacjach Pythona począwszy od Python 3.7
Boris

Odpowiedzi:

353

Znajdź to:

Jeśli items(), keys(), values(), iteritems(), iterkeys(), i itervalues()nazywane są bez interweniujących modyfikacji do słownika, listy będą bezpośrednio odpowiadać.

Na dokumentacji 2.x oraz dokumentacji 3.x .

nosklo
źródło
5
najwyraźniej stwierdzenie w dokumentacji 3.x jest jaśniejsze: „kolejność elementów będzie bezpośrednio odpowiadać”
Shaohua Li
4
Brakuje tego tekstu w dokumentacji 3.7. Mogę tylko założyć, że „Dict zachowuje kolejność wstawiania” w 3.7: mail.python.org/pipermail/python-dev/2017-December/151283.html
EliadL
80

Tak, to, co zaobserwowałeś, jest rzeczywiście gwarantowaną właściwością - listy kluczy (), wartości () i pozycje () zwracają się w odpowiedniej kolejności, jeśli dyktando nie zostanie zmienione. iterkeys () i c również iterują w tej samej kolejności, co odpowiednie listy.

Alex Martelli
źródło
1
Jednak w przypadku, gdy lista jest zmienione, Pandy dataframeoferuje alternatywę, gdzie elementy mogą być aktualizowane lub usuwane, a kolejność i rozmieszczenie indeks elementów w dict-jak struktury pozostają stałe.
Ville,
48

Tak, jest to gwarantowane w Pythonie 2.x :

Jeśli widoki kluczy, wartości i elementów są iterowane bez pośrednich modyfikacji słownika, kolejność elementów będzie bezpośrednio odpowiadać.

Bjorn
źródło
6

Dobre odniesienia do dokumentów. Oto w jaki sposób możesz zagwarantować zamówienie niezależnie od dokumentacji / realizacji:

k, v = zip(*d.iteritems())
Sassa NF
źródło
1
W python3.x użyj dict.items ()
Good Will
4

Zgodnie z http://docs.python.org/dev/py3k/library/stdtypes.html#dictionary-view-objects metody metody key (), values ​​() i items () zwrócą odpowiednie iteratory, których zamówienia korespondować. Jednak nie mogę znaleźć odniesienia do oficjalnej dokumentacji dla Pythona 2.x dla tej samej rzeczy.

O ile mogę powiedzieć, odpowiedź brzmi tak, ale tylko w python 3.0+

sykora
źródło
4

Co do tego jest warte, niektóre ciężko używane kody produkcyjne, które napisałem, oparte są na tym założeniu i nigdy nie miałem z tym problemu. Wiem, że to nie prawda :-)

Jeśli nie chcesz ryzykować, użyłbym iteritems (), jeśli możesz.

for key, value in myDictionary.iteritems():
    print key, value
Koen Bok
źródło
-2

Nie byłem zadowolony z tych odpowiedzi, ponieważ chciałem upewnić się, że eksportowane wartości mają taką samą kolejność, nawet przy użyciu różnych nagrań.

Tutaj z góry określasz kolejność kluczy, zwracane wartości będą zawsze miały tę samą kolejność, nawet jeśli dykt zmieni się lub użyjesz innego dykta.

keys = dict1.keys()
ordered_keys1 = [dict1[cur_key] for cur_key in keys]
ordered_keys2 = [dict2[cur_key] for cur_key in keys]
jlansey
źródło