Cum și când ar trebui să utilizați Defaultdict în Python?

În acest ghid, vei descoperi cum să folosești funcționalitatea `defaultdict` din modulul `collections` al limbajului Python. Această tehnică îți permite să gestionezi mai eficient erorile de tip `KeyError` atunci când lucrezi cu dicționare în Python.

În Python, un dicționar este o structură de date puternică, integrată, care stochează informații sub forma perechilor cheie-valoare. Folosești cheile pentru a accesa și modifica valorile din dicționar.

Totuși, când ai mai multe dicționare în codul tău Python, care sunt modificate în timpul execuției, vei întâlni frecvent erori de tip `KeyError`. Există mai multe metode prin care poți să le gestionezi.

În acest material, vei învăța:

  • Ce sunt erorile `KeyError` și de ce apar
  • Cum să gestionezi erorile `KeyError`
  • Cum să utilizezi `defaultdict` în Python, o subclasă care moștenește din clasa `dict`, pentru a manevra mai bine cheile lipsă

Să începem!

Ce sunt erorile `KeyError` în Python?

Când definești un dicționar în Python, trebuie să te asiguri de următoarele:

  • Cheile trebuie să fie unice – fără duplicări.
  • Când folosești o structură iterabilă existentă ca chei ale unui dicționar, ar trebui să preferi utilizarea unei colecții imutabile, cum ar fi un tuplu.

O cheie este considerată validă doar dacă este prezentă în dicționar; în caz contrar, se va genera o eroare de tip `KeyError`.

Să luăm exemplul următor, dicționarul `books_authors`, unde cheile sunt titlurile cărților, iar valorile sunt numele autorilor.

Poți să scrii codul în timp ce urmezi acest tutorial, într-un mediu REPL Python.

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

Poți folosi cheia (titlul cărții) pentru a accesa numele autorului.

books_authors['Hyperfocus']
    
'Chris Bailey'

Pentru a accesa toate perechile cheie-valoare din dicționar, poți apela metoda `items()` pe obiectul dicționar, după cum urmează:

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

Dacă încerci să accesezi valoarea unei chei care nu se află în dicționar, interpretorul Python va genera o `KeyError`. Apare această eroare când încercăm să accesăm valorile unor chei inexistente, cum ar fi „Grit” sau o „cheie inexistentă”.

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'
    

Așadar, cum gestionăm aceste erori `KeyError` în Python?

Există câteva metode pentru a face acest lucru, pe care le vom explora în secțiunea următoare.

Cum să gestionăm erorile `KeyError` în Python

Vom învăța cum să gestionăm erorile `KeyError` folosind:

  • Instrucțiuni condiționale `if-else`
  • Blocuri `try-except`
  • Metoda `.get()` a dicționarului

#1. Folosind instrucțiuni condiționale `if-else`

Una dintre cele mai simple metode de a gestiona `KeyError` este folosirea instrucțiunilor condiționale `if-else`.

În Python, instrucțiunile `if-else` au următoarea sintaxă generală:

if condition:
 	# executa acest cod
 else:
    # executa un alt cod
    
  • Dacă condiția este evaluată ca `True`, instrucțiunile din interiorul blocului `if` sunt executate.
  • Dacă condiția este evaluată ca `False`, instrucțiunile din blocul `else` sunt executate.

În acest exemplu, condiția verifică dacă cheia este prezentă în dicționar.

Dacă cheia este găsită, operatorul `in` va returna `True`, și codul din blocul `if` va fi executat, afișând valoarea corespunzătoare.

key = 'The Happiness Equation'
if key in books_authors:
  print(books_authors[key])
else:
  print('Ne pare rău, această cheie nu există!')

# Ieșire
# Neil Pasricha
    

Dacă cheia nu este prezentă în dicționar, operatorul `in` va returna `False`, iar corpul blocului `else` va fi executat. Acesta afișează un mesaj care indică faptul că cheia nu există.

key = 'non-existent-key'
if key in books_authors:
  print(books_authors[key])
else:
  print('Ne pare rău, această cheie nu există!')

# Ieșire
# Ne pare rău, această cheie nu există!
    

#2. Utilizarea instrucțiunilor `try-except`

O altă metodă obișnuită de a gestiona erorile `KeyError` este folosirea instrucțiunilor `try-except` în Python.

Analizează următorul fragment de cod:

key = 'non-existent-key'
try:
  print(books_authors[key])
except KeyError:
  print('Ne pare rău, această cheie nu există!')
    
  • Blocul `try` încearcă să recupereze valoarea corespunzătoare cheii furnizate.
  • Dacă cheia nu există, interpretorul generează o `KeyError`, care este tratată ca o excepție în blocul `except`.

#3. Folosind metoda `.get()`

În Python, poți utiliza metoda încorporată `.get()` a dicționarului pentru a gestiona cheile lipsă.

Sintaxa generală pentru utilizarea metodei `.get()` este `dict.get(cheie, valoare_implicită)`, unde `dict` este un obiect dicționar valid în Python.

– Dacă cheia este prezentă în dicționar, metoda `.get()` va returna valoarea acesteia.
– În caz contrar, va returna `valoare_implicită`.

În acest exemplu, `chei` este o listă de chei ale căror valori dorim să le accesăm. Iterăm prin această listă pentru a prelua valorile corespunzătoare din dicționarul `books_authors`.

Aici, am folosit metoda `.get()` cu valoarea implicită „Nu există”.

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

În codul de mai sus:

  • Pentru cheile care sunt prezente în dicționarul `books_authors`, metoda `.get()` va returna valorile corespunzătoare.
  • Când cheile nu există, în acest caz, „Grit” și „Make Time”, metoda `.get()` va returna valoarea implicită „Nu există”.
# Ieșire

Nu există
Chris Bailey
Nu există
Cal Newport
    

Toate metodele de mai sus ne ajută să gestionăm erorile de cheie. Totuși, acestea sunt detaliate și necesită gestionarea explicită a cheilor lipsă. Poți simplifica acest proces folosind `defaultdict` în locul unui dicționar obișnuit.

`Defaultdict` în Python

`Defaultdict` este o subclasă a clasei `dict` (dicționar). Așadar, moștenește comportamentul unui dicționar Python. În plus, gestionează și cheile lipsă în mod nativ.

`Defaultdict` este un tip de date container care este inclus în biblioteca standard a Python, în interiorul modulului `collections`.

Așadar, trebuie să îl imporți în mediul tău de lucru:

from collections import defaultdict
    

Iată sintaxa generală pentru utilizarea `defaultdict`:

defaultdict(default_factory)
    

Poți specifica o funcție apelabilă, cum ar fi `int`, `float` sau `list`, ca atribut `default_factory`. Dacă nu oferi o valoare pentru `default_factory`, aceasta va fi `None` implicit.

Când cheia pe care o cauți nu este prezentă, este declanșată metoda `__missing__()`, care va deduce valoarea implicită din `default_factory`. Apoi, returnează această valoare implicită.

În concluzie:

  • În Python, `defaultdict` returnează valoarea implicită atunci când cheia nu este prezentă.
  • De asemenea, adaugă această pereche cheie-valoare implicită la dicționar, pe care apoi o poți modifica.

Exemple Python `Defaultdict`

În continuare, vom analiza câteva exemple pentru a înțelege cum funcționează `defaultdict` în Python.

`Defaultdict` în Python cu valoare întreagă implicită

Mai întâi, importă `defaultdict` din modulul `collections`.

from collections import defaultdict
import random
    

Să creăm prețuri implicite.

prices = defaultdict(int)
    

Acum, completăm dicționarul `prices` folosind elementele din lista de fructe ca și chei. Apoi, eșantionăm aleatoriu valori din `price_list` pentru a obține valorile.

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

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

Să analizăm perechile cheie-valoare din dicționarul `prices`.

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

Similar unui dicționar Python obișnuit, poți accesa valorile din dicționarul `prices` folosind cheile:

prices['apple']
# 23
    

Acum, să încercăm să accesăm prețul unui fruct care nu este prezent, să zicem „orange”. Observăm că returnează valoarea implicită zero.

prices['orange']
# 0
    

Dacă afișăm dicționarul, vedem că o nouă cheie „orange” a fost adăugată, cu valoarea integrală implicită zero.

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

`Defaultdict` în Python cu `list` ca valoare implicită

Să definim `student_majors` ca un `defaultdict` de liste. Numele specializărilor sunt cheile, iar valorile sunt listele de studenți care urmează fiecare specializare, cum ar fi matematică, economie, informatică și altele.

from collections import defaultdict
students_majors = defaultdict(list)
    

Dacă încercăm să accesăm lista de studenți corespunzătoare specializării „Economics”, `defaultdict` va returna o listă goală, fără erori de cheie!

students_majors['Economics']
# []
    

Acum, avem o listă goală mapată la specializarea „Economics”. Așadar, putem adăuga elemente la această listă folosind metoda `.append()` a listei.

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

A fost creată o intrare pentru „Economics” în dicționarul standard `student_majors`.

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

Poți adăuga mai mulți studenți la maparea listei pentru specializarea Economics, poți adăuga o nouă specializare și multe altele!

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

Concluzie

Sper că acest ghid te-a ajutat să înțelegi cum și când ar trebui să folosești `defaultdict` în Python. După ce rulezi exemplele de cod din acest tutorial, poți încerca să utilizezi `defaultdict` ca structură de date preferată în proiectele tale, atunci când este necesar.

Iată un rezumat a ceea ce ai învățat în acest tutorial.

  • Când lucrezi cu un dicționar Python, vei întâlni adesea erori `KeyError`.
  • Pentru a gestiona astfel de erori `KeyError`, poți folosi câteva metode. Poți utiliza instrucțiuni condiționale, blocuri `try-except` sau metoda `.get()`. Dar tipul de date `defaultdict` din modulul `collections` poate simplifica gestionarea `KeyError`.
  • Poți utiliza `defaultdict(default_factory)`, unde `default_factory` este o funcție apelabilă validă.
  • Când cheia nu este prezentă în `defaultdict`, valoarea implicită (dedusă din `default_factory`) și cheia sunt adăugate la `defaultdict`.

Apoi, poți consulta ghidul despre funcția `map` din Python.