Czy słowniki są uporządkowane w Pythonie 3.6+?
Słowniki są uporządkowane w Pythonie 3.6 (przynajmniej pod implementacją CPython) w przeciwieństwie do poprzednich wcieleń. Wydaje się to istotną zmianą, ale jest to tylko krótki akapit w dokumentacji. Jest on opisany jako szczegóły implementacji CPython, a nie Funkcja języka, ale również oznacza, że może stać się standardem w przyszłości.
W Jaki Sposób nowa implementacja słownika działa lepiej niż starsza, zachowując kolejność elementów?
Oto tekst z dokumentacji:
dict()
teraz używa" zwartej " reprezentacji zapoczątkowanej przez PyPy . Użycie pamięci nowej metody dict () jest od 20% do 25% mniejsze w porównaniu z Pythonem 3.5. PEP 468 (zachowanie kolejności * * kwargów w funkcji.) jest realizowany przez to. Aspekt zachowania porządku w tej nowej implementacji jest uważany za szczegółową implementację i nie należy na niej polegać (może się to zmienić w przyszłości, ale jest chciał mieć tę nową implementację dict w języku przez kilka wydań przed zmianą specyfikacji języka na zlecenie porządku-zachowując semantykę dla wszystkich obecnych i przyszłych implementacji Pythona; pomaga to również zachować wsteczną kompatybilność ze starszymi wersjami języka, w których nadal obowiązuje losowa kolejność iteracji, np. Python 3.5). (Autor: INADA Naoki w wydanie 27350. Pomysł pierwotnie zasugerowany przez Raymonda Hettingera .)
Update Grudzień 2017: dict
s utrzymanie zamówienia wstawiania jest gwarantowane dla Pythona 3.7
3 answers
Czy słowniki są uporządkowane w Pythonie 3.6+?
Są wstawianie uporządkowane[1]. Od wersji Python 3.6, dla implementacji Pythona CPython, słowniki zapamiętują kolejność wstawianych elementów . jest to uważane za szczegóły implementacji w Pythonie 3.6; musisz użyć OrderedDict
, Jeśli chcesz, aby kolejność wstawiania była gwarantowana w innych implementacjach Pythona (i innych uporządkowanych zachowanie[1]).
W Pythonie 3.7, nie jest to już szczegóły implementacji, a zamiast tego staje się cechą języka. from a python-dev message by GvR :
Niech tak będzie. "Dict utrzymuje porządek wstawiania" to orzeczenie. Dzięki!
Oznacza to po prostu, że możesz na tym polegać . Inne implementacje Pythona muszą również oferować wstawiony słownik, jeśli chcą być zgodne implementacja Pythona 3.7.
W Jaki Sposób implementacja słownika Pythona
3.6
działa lepiej[2] niż starszy, zachowując porządek elementów?
Zasadniczo, przez utrzymanie dwóch tablic .
Pierwsza tablica,
dk_entries
, przechowuje wpisy ( typuPyDictKeyEntry
) do słownika w kolejności, w jakiej zostały wstawione. Zachowanie porządku uzyskuje się przez to, że jest to tylko dodatek tablica, gdzie nowe pozycje są zawsze wstawiane na końcu (kolejność wstawiania).-
Drugi,
dk_indices
, przechowuje indeksy dla tablicydk_entries
(to znaczy wartości, które wskazują pozycję odpowiedniego wpisu wdk_entries
). Tablica ta działa jak tablica hash. Gdy klucz jest zahaszowany, prowadzi do jednego z indeksów przechowywanych wdk_indices
, a odpowiadający mu wpis jest pobierany przez indeksowaniedk_entries
. Ponieważ przechowywane są tylko indeksy, Typ tej tablicy zależy od ogólnej wielkości słownik (od typuint8_t
(1
bajt) doint32_t
/int64_t
(4
/8
bajtów) na32
/64
bit builds)
W poprzedniej implementacji trzeba było przydzielać nieliczną tablicę typu PyDictKeyEntry
i rozmiaru dk_size
; niestety, spowodowało to również dużo pustej przestrzeni, ponieważ ta tablica nie mogła być większa niż 2/3 * dk_size
pełna ze względu na wydajność. (a pusta przestrzeń wciąż miała PyDictKeyEntry
Rozmiar!).
Teraz tak nie jest, ponieważ tylko wymagane wpisy są przechowywane (te, które zostały wstawione) i rzadka tablica typu intX_t
(X
w zależności od wielkości dict) 2/3 * dk_size
jest zachowywana pełna. Pusta przestrzeń została zmieniona z typu PyDictKeyEntry
na intX_t
.
Możesz zobaczyć pełną rozmowę na Python-Dev dotyczącą tego funkcja jeśli zainteresowany, jest to dobra lektura.
Na przykład słownik:
d = {'timmy': 'red', 'barry': 'green', 'guido': 'blue'}
Jest obecnie przechowywany jako:
entries = [['--', '--', '--'], [-8522787127447073495, 'barry', 'green'], ['--', '--', '--'], ['--', '--', '--'], ['--', '--', '--'], [-9092791511155847987, 'timmy', 'red'], ['--', '--', '--'], [-6480567542315338377, 'guido', 'blue']]
Zamiast tego dane powinny być zorganizowane w następujący sposób:
indices = [None, 1, None, None, None, 0, None, 2] entries = [[-9092791511155847987, 'timmy', 'red'], [-8522787127447073495, 'barry', 'green'], [-6480567542315338377, 'guido', 'blue']]
Jak widać teraz wizualnie, w oryginalnej propozycji, dużo miejsca jest zasadniczo pusty, aby zmniejszyć kolizje i przyspieszyć wyszukiwanie. Dzięki nowemu podejściu zmniejszasz wymaganą pamięć, przesuwając skąpość tam, gdzie jest ona naprawdę wymagana, w indeksach.
[1]: mówię "wstawianie uporządkowane", a nie "uporządkowane", ponieważ, wraz z istnieniem OrderedDict," uporządkowane " sugeruje dalsze zachowanie, którego obiekt dict
nie zapewnia. OrderedDicts są odwracalne, zapewniają metody wrażliwe na zamówienie i, głównie, zapewniają sensowne zamówienie testy równości (==
, !=
). dict
S obecnie nie oferuje żadnego z tych zachowań / metod.
[2]: nowa implementacja słownika działa lepiej Z pamięcią , ponieważ jest zaprojektowana bardziej kompaktowo; to jest główna korzyść tutaj. Jeśli chodzi o szybkość, różnica nie jest tak drastyczna, są miejsca, w których Nowy dict może wprowadzić niewielkie regresje (key-lookups, na przykład ), podczas gdy w innych (iteracja i zmiana rozmiaru przychodzą na myśl) wydajność boost powinien być obecny.
Ogólnie rzecz biorąc, wydajność słownika, szczególnie w rzeczywistych sytuacjach, poprawia się ze względu na wprowadzoną zwartość.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-10 17:23:38
Poniżej znajduje się odpowiedź na pierwsze pytanie:
Czy powinienem używać
dict
LUBOrderedDict
w Pythonie 3.6?
Myślę, że to zdanie z dokumentacji wystarczy, aby odpowiedzieć na twoje pytanie
Aspekt zachowania porządku w tej nowej implementacji jest uważany za szczegółową implementację i nie należy na niej polegać
dict
nie ma być jednoznacznie uporządkowanym zbiorem, więc jeśli chcesz pozostać spójny i nie polegać na stronie efekt nowej implementacji należy trzymać się OrderedDict
.
Uczyń swój kod przyszłościowym:)
Jest dyskusja na ten temat tutaj .
EDIT: Python 3.7 zachowa to jako funkcję zobacz
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-02 14:06:23
Update:
Guido van Rossum ogłosił na liście dyskusyjnej , że począwszy od Pythona 3.7 dict
s we wszystkich implementacjach Pythona musi zachować kolejność wstawiania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-14 17:38:50