Jak a kdy byste měli použít Defaultdict v Pythonu?

V tomto návodu se dozvíte, jak efektivně využít `defaultdict` z knihovny `collections` v Pythonu, abyste lépe zvládali chyby `KeyError` při práci se slovníky.

Slovník v Pythonu je klíčová datová struktura pro ukládání dat ve formě párů klíč-hodnota. Klíče slouží jako index pro přístup k jednotlivým hodnotám.

Nicméně, při práci s více slovníky, které se dynamicky mění, můžete narazit na chyby `KeyError`. Existuje několik strategií, jak se s nimi vypořádat.

V tomto článku se naučíte:

  • Co přesně jsou chyby `KeyError` a proč se objevují.
  • Jakými způsoby lze tyto chyby řešit.
  • Jak využít `defaultdict`, podtřídu odvozenou od vestavěné třídy `dict`, pro lepší a elegantnější zpracování chybějících klíčů.

Začněme!

Co jsou chyby `KeyError` v Pythonu?

Při vytváření slovníků v Pythonu je důležité mít na paměti následující:

  • Klíče musí být unikátní – bez duplikátů.
  • Pokud jako klíče používáte iterovatelné objekty, preferujte neměnné kolekce, jako jsou n-tice.

Klíč je platný pouze tehdy, pokud existuje ve slovníku. V opačném případě dojde k chybě `KeyError`.

Představme si slovník `books_authors`, kde klíče představují názvy knih a hodnoty jména autorů.

Pro účely tohoto návodu můžete kódovat v Python REPL.

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

Pro získání jména autora použijeme klíč (název knihy).

books_authors['Hyperfocus']
'Chris Bailey'

K zobrazení všech párů klíč-hodnota ve slovníku můžeme použít metodu `items()`, jak je ukázáno níže:

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

Pokud se pokusíte přistoupit k hodnotě klíče, který ve slovníku neexistuje, Python vyvolá chybu `KeyError`. Tato chyba nastane, když se snažíme získat přístup k hodnotě pro klíče jako ‚Grit‘ a ‚neexistující klíč‘.

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 tedy můžeme tyto chyby `KeyError` řešit?

Existuje několik metod a seznámíme se s nimi v následující části.

Jak zpracovat chyby `KeyError` v Pythonu

Podívejme se, jak zacházet s chybami `KeyError` pomocí:

  • Podmíněných příkazů `if-else`.
  • Bloků `try-except`.
  • Metody `.get()` slovníku.

#1. Použití podmíněných příkazů `if-else`

Jednou z nejjednodušších metod pro zpracování chyb `KeyError` v Pythonu je použití příkazů `if-else`.

V Pythonu mají příkazy `if-else` následující strukturu:

 if podmínka:
 	# proveď toto
 else:
    # proveď něco jiného 
  • Pokud je podmínka `True`, provedou se příkazy uvnitř bloku `if`.
  • Pokud je podmínka `False`, provedou se příkazy uvnitř bloku `else`.

V našem případě je podmínkou ověření, zda klíč existuje ve slovníku.

Pokud klíč ve slovníku je, operátor `in` vrátí `True`, a vypíše se odpovídající hodnota.

key = 'The Happiness Equation'
if key in books_authors:
  print(books_authors[key])
else:
  print('Omlouvám se, tento klíč neexistuje!')

# Výstup
# Neil Pasricha

Pokud klíč ve slovníku není, operátor `in` vrátí `False`, a provede se blok `else`. Vypíše se zpráva o neexistenci klíče.

key = 'non-existent-key'
if key in books_authors:
  print(books_authors[key])
else:
  print('Omlouvám se, tento klíč neexistuje!')

# Výstup
# Omlouvám se, tento klíč neexistuje!

#2. Použití příkazů `try-except`

Další běžnou metodou pro zpracování `KeyError` je použití příkazů `try-except` v Pythonu.

Prohlédněte si následující blok kódu:

key = 'non-existent-key'
try:
  print(books_authors[key])
except KeyError:
  print('Omlouvám se, tento klíč neexistuje!')
  • Blok `try` se pokusí získat hodnotu pro zadaný klíč.
  • Pokud klíč neexistuje, Python vyvolá chybu `KeyError`, která se zpracuje v bloku `except`.

#3. Použití metody `.get()`

V Pythonu můžete pro manipulaci s chybějícími klíči použít vestavěnou metodu `.get()` slovníku.

Obecná syntaxe pro použití metody `get()` je `dict.get(key, default_value)`, kde `dict` je platný slovník v Pythonu.

– Pokud klíč existuje ve slovníku, metoda `get()` vrátí jeho hodnotu.
– V opačném případě vrátí výchozí hodnotu.

V tomto příkladu máme seznam klíčů, ke kterým chceme přistoupit. Procházíme seznam a získáváme odpovídající hodnoty ze slovníku `books_authors`.

Používáme metodu `.get()` s výchozí hodnotou ‚Neexistuje‘.

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

V kódu výše:

  • Pro klíče, které existují ve slovníku `books_authors`, metoda `.get()` vrací jejich hodnoty.
  • Když klíče neexistují, v tomto případě ‚Grit‘ a ‚Make Time‘, metoda `.get()` vrací výchozí hodnotu ‚Neexistuje‘.
# Výstup

Neexistuje
Chris Bailey
Neexistuje
Cal Newport

Všechny tyto metody nám pomáhají při řešení chyb `KeyError`, ale jsou detailní a vyžadují explicitní zpracování chybějících klíčů. Tento proces můžeme zjednodušit použitím `defaultdict` místo běžného slovníku.

`Defaultdict` v Pythonu

`Defaultdict` je podtřída třídy `dict` (slovník). Dědí tedy vlastnosti běžného slovníku v Pythonu. Navíc, dokáže automaticky zpracovat chybějící klíče.

`Defaultdict` je datový typ kontejneru, který je součástí standardní knihovny Pythonu v modulu `collections`.

Musíme jej importovat do našeho prostředí:

from collections import defaultdict

Zde je obecná syntaxe pro použití `defaultdict`:

defaultdict(default_factory)

Jako atribut `default_factory` můžeme zadat callable, jako `int`, `float` nebo `list`. Pokud nezadáte hodnotu pro `default_factory`, výchozí je `None`.

Když klíč, který hledáte, neexistuje, spustí se metoda `__missing__()` a ta odvodí výchozí hodnotu z `default_factory`. Poté vrátí tuto výchozí hodnotu.

Shrnuto:

  • V Pythonu `defaultdict` vrací výchozí hodnotu, když klíč chybí.
  • Také přidá tento pár klíč-výchozí hodnota do slovníku, který můžete dále upravovat.

Příklady `defaultdict` v Pythonu

Prozkoumejme několik příkladů, abychom pochopili, jak `defaultdict` v Pythonu funguje.

`Defaultdict` s výchozí celočíselnou hodnotou

Nejprve importujte `defaultdict` z modulu `collections`.

from collections import defaultdict
import random

Vytvoříme výchozí ceny.

prices = defaultdict(int)

Nyní naplníme slovník cen položkami ze seznamu ovoce jako klíči. A náhodně vybereme hodnoty z ceníku, abychom získali hodnoty.

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

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

Podívejme se na páry klíč-hodnota v `prices`:

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

Stejně jako u běžného slovníku v Pythonu můžeme přistupovat k hodnotám `defaultdict` `prices` pomocí klíčů:

prices['apple']
# 12

Zkusme získat cenu ovoce, které ve slovníku neexistuje, například „orange“. Vidíme, že vrací výchozí hodnotu nula.

prices['orange']
# 0

Pokud vytiskneme slovník, vidíme, že byl přidán nový klíč ‚orange‘ s výchozí celočíselnou hodnotou nula.

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

`Defaultdict` se seznamem jako výchozí hodnotou

Definujme `students_majors` jako `defaultdict` s výchozím seznamem. Názvy oborů jsou klíči a hodnotami jsou seznamy studentů, kteří studují jednotlivé obory, jako matematika, ekonomie, informatika a další.

from collections import defaultdict
students_majors = defaultdict(list)

Pokud se pokusíme otevřít seznam studentů odpovídající ‚Economics‘, `defaultdict` vrátí prázdný seznam; žádné chyby `KeyError`!

students_majors['Economics']
# []

Nyní máme prázdný seznam namapovaný na obor ‚Economics‘. Můžeme do něj přidávat prvky pomocí metody `.append()` seznamu.

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

Ve slovníku `students_majors` byl vytvořen záznam pro ‚Economics‘.

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

Můžeme přidat další studenty do seznamu pro ekonomii, přidat nový obor, a mnoho dalšího!

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

Závěr

Doufám, že vám tento návod pomohl pochopit, jak a kdy použít `defaultdict` v Pythonu. Po vyzkoušení příkladů v tomto článku můžete zvážit použití `defaultdict` jako preferované datové struktury ve vašich projektech.

Zde je shrnutí toho, co jste se v tomto návodu naučili.

  • Při práci se slovníky v Pythonu se často setkáváme s chybami `KeyError`.
  • K řešení takových chyb existuje několik podrobných metod: podmíněné příkazy, bloky `try-except` nebo metoda `.get()`. Datový typ `defaultdict` z modulu `collections` však může zjednodušit manipulaci s chybami `KeyError`.
  • Můžete použít `defaultdict(default_factory)`, kde `default_factory` je platný callable.
  • Pokud klíč v `defaultdict` neexistuje, do `defaultdict` se přidá výchozí hodnota (odvozená z `default_factory`) spolu s klíčem.

Podívejte se také na návod k funkci `map` v Pythonu.