Jak i kiedy należy używać Defaultdict w Pythonie?

Photo of author

By maciekx

W tym poradniku zgłębisz tajniki wykorzystania defaultdict z modułu collections w Pythonie, co pozwoli Ci skuteczniej zarządzać błędami KeyErrors podczas pracy ze słownikami.

Słownik w Pythonie to potężna wbudowana struktura danych, służąca do przechowywania informacji w parach klucz-wartość. Klucze są Twoim „wejściem” do słownika, umożliwiając dostęp do przypisanych im wartości.

Jednakże, w projektach, gdzie często operujesz na wielu słownikach, które są dynamicznie modyfikowane, nierzadko napotkasz błędy typu KeyError. Istnieje szereg technik pozwalających na eleganckie radzenie sobie z tym problemem.

W niniejszym samouczku dowiesz się:

  • Czym dokładnie są błędy KeyError i skąd się biorą.
  • Jak efektywnie zarządzać błędami KeyError.
  • Jak korzystać z defaultdict, specjalnej podklasy dziedziczącej po wbudowanej klasie dict, która ułatwia obsługę brakujących kluczy.

Zacznijmy!

Czym są błędy KeyError w Pythonie?

Tworząc słownik w Pythonie, musisz mieć na uwadze kilka kluczowych zasad:

  • Klucze muszą być unikatowe, nie mogą się powtarzać.
  • Gdy wykorzystujesz elementy iteracyjne jako klucze słownika, preferuj niezmienne kolekcje, takie jak tuple (krotki).

Klucz jest ważny tylko wtedy, gdy istnieje w słowniku; w przeciwnym razie pojawia się błąd KeyError.

Rozważmy przykład słownika o nazwie `books_authors`, w którym kluczami są tytuły książek, a wartościami imiona i nazwiska autorów.

Możesz śledzić ten samouczek, wykonując kod w Python REPL.

books_authors = {
    'Deep Work':'Cal Newport',
    'Hyperfocus':'Chris Bailey',
    'Pivot':'Jenny Blake',
    'The Happiness Equation':'Neil Pasricha'
}

Używając klucza (tytułu książki), możesz uzyskać dostęp do nazwiska autora.

books_authors['Hyperfocus']
'Chris Bailey'

Aby uzyskać dostęp do wszystkich par klucz-wartość w słowniku, wywołaj metodę `items()` obiektu słownika, jak pokazano poniżej:

for book,author in books_authors.items():
  print(f"'{book}' autorstwa {author}")
'Deep Work' autorstwa Cal Newport
'Hyperfocus' autorstwa Chris Bailey
'Pivot' autorstwa Jenny Blake
'The Happiness Equation' autorstwa Neil Pasricha

Jeśli spróbujesz uzyskać dostęp do wartości klucza, który nie istnieje w słowniku, interpreter Pythona zgłosi wyjątek KeyError. Błąd KeyError pojawia się, gdy próbujesz uzyskać dostęp do wartości nieistniejących kluczy, takich jak „Grit” i „nieistniejący klucz”.

books_authors['Grit']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-6-e1a4486f5ced> in <module>
----> 1 books_authors['Grit']

KeyError: 'Grit'
books_authors['non-existent-key']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-7-a3efd56f69e5> in <module>
----> 1 books_authors['non-existent-key']

KeyError: 'non-existent-key'

Jak więc radzić sobie z błędami KeyError w Pythonie?

Istnieje kilka metod, które poznasz w kolejnej sekcji.

Jak zarządzać błędami KeyError w Pythonie?

Przeanalizujmy, jak radzić sobie z błędami KeyError, korzystając z:

  • Instrukcji warunkowych if-else.
  • Bloków try-except.
  • Metody .get() słownika.

#1. Wykorzystanie instrukcji warunkowych if-else

Jednym z najprostszych sposobów obsługi błędów KeyError w Pythonie jest użycie instrukcji warunkowych if-else.

W Pythonie instrukcje if-else mają następującą ogólną składnię:

 if warunek:
    # wykonaj to
 else:
    # wykonaj coś innego 
  • Jeżeli warunek jest prawdziwy, wykonywane są instrukcje w bloku if.
  • Jeżeli warunek jest fałszywy, wykonywane są instrukcje w bloku else.

W tym przykładzie warunkiem jest sprawdzenie, czy dany klucz istnieje w słowniku.

Jeżeli klucz znajduje się w słowniku, operator `in` zwróci True, a blok `if` zostanie wykonany, wyświetlając odpowiednią wartość.

key = 'The Happiness Equation'
if key in books_authors:
  print(books_authors[key])
else:
  print('Przykro mi, ten klucz nie istnieje!')

# Wyjście
# Neil Pasricha

Jeżeli klucz nie występuje w słowniku, operator `in` zwróci False i zostanie wykonany blok `else`. Wyświetli on komunikat o nieistniejącym kluczu.

key = 'non-existent-key'
if key in books_authors:
  print(books_authors[key])
else:
  print('Przykro mi, ten klucz nie istnieje!')

# Wyjście
# Przykro mi, ten klucz nie istnieje!

#2. Wykorzystanie instrukcji try-except

Innym powszechnym podejściem do obsługi błędów KeyError jest zastosowanie instrukcji try-except w Pythonie.

Spójrz na poniższy fragment kodu:

key = 'non-existent-key'
try:
  print(books_authors[key])
except KeyError:
  print('Przykro mi, ten klucz nie istnieje!')
  • Blok `try` próbuje pobrać wartość przypisaną do danego klucza.
  • Jeżeli klucz nie jest obecny, interpreter zgłosi błąd KeyError, który zostanie przechwycony jako wyjątek w bloku `except`.

#3. Wykorzystanie metody .get()

W Pythonie możesz użyć wbudowanej metody słownikowej .get() do obsługi brakujących kluczy.

Ogólna składnia metody `get()` to `dict.get(klucz, wartość_domyślna)`, gdzie `dict` jest poprawnym obiektem słownika w Pythonie.

– Jeżeli klucz jest obecny w słowniku, metoda `get()` zwróci jego wartość.
– W przeciwnym razie zwróci wartość domyślną.

W tym przykładzie klucze to lista kluczy, do których wartości chcemy uzyskać dostęp. Przechodzimy przez listę kluczy, aby pobrać odpowiadające im wartości ze słownika `books_authors`.

Użyliśmy tutaj metody `.get()` z wartością domyślną „Nie istnieje”.

keys = ['Grit','Hyperfocus','Make Time','Deep Work']
for key in keys:
  print(books_authors.get(key,'Nie istnieje'))

W powyższym kodzie:

  • Dla kluczy, które znajdują się w słowniku `books_authors`, metoda `.get()` zwraca odpowiadające im wartości.
  • Gdy klucze nie istnieją, w tym przypadku „Grit” i „Make Time”, metoda `.get()` zwraca wartość domyślną „Nie istnieje”.
# Wyjście

Nie istnieje
Chris Bailey
Nie istnieje
Cal Newport

Wszystkie wymienione metody pomagają nam w obsłudze błędów KeyError. Są jednak nieco rozwlekłe i wymagają od nas explicitnego radzenia sobie z brakującymi kluczami. Możesz uprościć ten proces, używając defaultdict zamiast standardowego słownika.

Defaultdict w Pythonie

Defaultdict to podklasa klasy Dictionary (dict). Dziedziczy więc właściwości słownika Pythona. Co więcej, ma wbudowaną obsługę brakujących kluczy.

Defaultdict jest typem danych kontenerowych wbudowanym w standardową bibliotekę Pythona – znajduje się w module `collections`.

Musisz więc zaimportować go do swojego środowiska pracy:

from collections import defaultdict

Oto ogólna składnia użycia defaultdict:

defaultdict(default_factory)

Jako atrybut `default_factory` możesz określić wywoływalne, takie jak `int`, `float` lub `list`. Jeżeli nie podasz wartości dla `default_factory`, domyślną wartością będzie None.

Gdy szukany klucz nie jest obecny, wywoływana jest metoda `__missing__()`, która na podstawie `default_factory` określa domyślną wartość. Następnie ta domyślna wartość jest zwracana.

Podsumowując:

  • W Pythonie defaultdict zwraca wartość domyślną, gdy klucz nie istnieje.
  • Dodaje również tę parę klucz-wartość domyślną do słownika, którą następnie można modyfikować.

Przykłady defaultdict w Pythonie

Teraz przeanalizujemy kilka przykładów, aby lepiej zrozumieć, jak działa defaultdict w Pythonie.

Defaultdict w Pythonie z domyślną wartością całkowitą

Najpierw zaimportuj `defaultdict` z modułu `collections`.

from collections import defaultdict
import random

Stwórzmy słownik z domyślnymi cenami.

prices = defaultdict(int)

Teraz wypełnimy słownik `prices`, używając nazw owoców z listy jako kluczy. Wartości będą losowo wybrane z cennika.

price_list = [10,23,12,19,5]
fruits = ['apple','strawberry','pomegranate','blueberry']

for fruit in fruits:
  prices[fruit] = random.choice(price_list)

Spójrzmy na pary klucz-wartość w słowniku `prices`.

print(prices.items())
dict_items([('apple', 12), ('blueberry', 19), ('pomegranate', 5), ('strawberry', 10)])

Podobnie jak w zwykłym słowniku Pythona, możesz uzyskać dostęp do wartości `defaultdict` `prices` za pomocą kluczy:

prices['apple']
# 23

Spróbujmy teraz sprawdzić cenę owocu, który nie istnieje, na przykład „orange”. Zauważ, że zwracana jest domyślna wartość zero.

prices['orange']
# 0

Jeżeli teraz wydrukujemy słownik, zobaczymy, że został dodany nowy klucz „orange” z domyślną liczbą całkowitą równą zero.

print(prices.items())
dict_items([('apple', 12), ('blueberry', 19), ('pomegranate', 5), ('strawberry', 10), ('orange', 0)])

Defaultdict w Pythonie z listą jako wartością domyślną

Zdefiniujmy `Student_Majors` jako domyślny słownik list. Kluczami będą nazwy kierunków. Wartościami listy studentów studiujących dany kierunek, np. matematykę, ekonomię, informatykę itp.

from collections import defaultdict
students_majors = defaultdict(list)

Jeżeli spróbujemy uzyskać dostęp do listy studentów przypisanych do „Economics”, defaultdict zwróci pustą listę; nie ma żadnego błędu KeyError!

students_majors['Economics']
# []

Mamy teraz pustą listę przypisaną do kierunku „Economics”. Możemy więc dodawać elementy do tej listy za pomocą metody `.append()`.

students_majors['Economics'].append('Alex')

W domyślnym słowniku `students_majors` utworzono wpis dla „Economics”.

print(students_majors)
defaultdict(<class 'list'>, {'Economics': ['Alex']})

Możesz dodać więcej studentów do listy przypisanej do kierunku „Economics”, dodać nowy kierunek i wiele więcej!

students_majors['Economics'].append('Bob')
students_majors['Math'].append('Laura')
print(students_majors)
defaultdict(<class 'list'>, {'Economics': ['Alex', 'Bob'], 'Math': ['Laura']})

Podsumowanie

Mam nadzieję, że ten samouczek pomógł Ci zrozumieć, jak i kiedy warto używać defaultdict w Pythonie. Po przetestowaniu przykładów kodu z tego samouczka, możesz wykorzystać defaultdict jako preferowaną strukturę danych w swoich projektach.

Oto podsumowanie tego, czego nauczyłeś się w tym poradniku.

  • Podczas pracy ze słownikami Pythona często spotyka się błędy KeyError.
  • Aby poradzić sobie z takimi błędami, można użyć kilku metod, takich jak instrukcje warunkowe, bloki try-except, czy metoda .get(). Jednak typ danych defaultdict z modułu `collections` może uprościć obsługę błędów KeyError.
  • Można użyć `defaultdict(default_factory)`, gdzie `default_factory` jest poprawnym elementem wywoływalnym.
  • Jeżeli klucz nie jest obecny w defaultdict, domyślna wartość (wywnioskowana z `default_factory`) i klucz są dodawane do defaultdict.

Następnie zapoznaj się z samouczkiem dotyczącym funkcji mapowania w Pythonie.


newsblog.pl