programowanieProgramista Python

Czym jest słownik (dict) w Pythonie, jak jest zbudowany od środka i w jakich przypadkach typ dict może zachowywać się niestandardowo?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

Historia pytania:

Słowniki (dict) — jeden z podstawowych typów danych w Pythonie, reprezentujący strukturę „klucz-wartość”. Słowniki pojawiły się w pierwszym Pythonie, ale ich wewnętrzna implementacja i cechy zachowania były stale doskonalone (na przykład w Pythonie 3.7 gwarantowany jest porządek wstawiania).

Problem:

Zrozumienie działania słownika jest niezbędne do efektywnego pisania kodu. Bez znajomości szczegółów pojawiają się błędy przy używaniu typów mutowalnych jako kluczy, podczas kopiowania zagnieżdżonych słowników, a także przy niestandardowych operacjach.

Rozwiązanie:

Słownik jest zrealizowany jako tablica haszująca, klucze muszą być koniecznie haszowalne (niemutowalne). Dostęp do wartości za pomocą klucza działa blisko O(1), ale w pewnych warunkach występują szczególności — na przykład przy kolizjach lub pracy z dużymi ilościami danych.

Przykład kodu:

person = {'name': 'Alice', 'age': 30} person['city'] = 'Moscow' print(person['name']) # Alice

Kluczowe cechy:

  • Klucze muszą być niemutowalne i haszowalne (na przykład, str, int, tuple bez obiektów mutowalnych).
  • Słownik w Pythonie 3.7 i nowszych zachowuje porządek wstawiania elementów.
  • dict doskonale nadaje się do wyszukiwania, agregacji, odwzorowań.

Pytania z pułapką.

Czy można użyć listy (list) jako klucza w dict?

Nie, listy są mutowalne i nie są haszowalne. Próba użycia listy spowoduje błąd.

d = {} d[[1, 2, 3]] = 'value' # TypeError: unhashable type: 'list'

Co się stanie, jeśli jako klucza użyjesz dwóch krotek o tej samej zawartości?

Jeśli obie krotki zawierają te same dane i same są niemutowalne, są uważane za równe, a klucze w słowniku będą się pokrywać:

t1 = (1, 2) t2 = (1, 2) d = {t1: 'a'} print(d[t2]) # 'a'

Czy porządek przeszukiwania elementów słownika zmieni się przy kopiowaniu?

W wersjach Python 3.7+ porządek zostanie zachowany. W starszych — porządek przeszukiwania nie jest gwarantowany.

d1 = {'a': 1, 'b': 2} d2 = dict(d1) print(list(d2)) # ['a', 'b']

Typowe błędy i antywzorce

  • Użycie mutowalnego typu jako klucza (na przykład, list lub dict).
  • Błędy przy kopiowaniu: prosty operator = nie tworzy kopii, a robi nowy „wskaźnik” do tego samego obiektu.
  • Nadużywanie dict.get() bez sprawdzania na None może prowadzić do nieoczekiwanych błędów, jeśli wartość == None.

Przykład z życia

Negatywny przypadek

Programista przechowuje listy jako klucze, błędnie sądząc, że tuple i list w Pythonie są równoważne jako klucze. Otrzymuje wyjątki takie jak „unhashable type”.

Zalety:

Można szybko spróbować czegoś „na kolanie”, używać dowolnych struktur.

Wady:

Błędy w czasie wykonywania, błędy przy przetwarzaniu danych.

Pozytywny przypadek

Używane są tylko niemutowalne (haszowalne) obiekty jako klucze, krotki są przemyślane tak, aby nie zawierały elementów mutowalnych.

Zalety:

Szybkość wyszukiwania po kluczu, niezawodność struktury, łatwe przetwarzanie i kopiowanie.

Wady:

Jeśli dane są skomplikowane, wymagana jest dodatkowa obróbka, aby przekształcić strukturę w formę niemutowalną (na przykład, serializacja wewnątrz tuple).