Podstawy Pythona: słowniki, funkcje i JSON

Michał Feliksik
3 min read
Podstawy Pythona: słowniki, funkcje i JSON

Wprowadzenie

W poprzednim wpisie omówiliśmy różnicę między () a [], listy, krotki i podstawowe operacje na macierzach. Dziś czas na kolejny krok: słowniki, czyli najważniejszą strukturę danych do przechowywania par klucz-wartość, funkcje z elastyczną liczbą argumentów oraz format JSON, w którym prędzej czy później zapisze się każda konfiguracja czy odpowiedź z zewnętrznego źródła. Wciąż bez LLM-ów — najpierw fundamenty.

Słowniki — dane po nazwie, nie po pozycji

Lista i krotka odwołują się do elementów po indeksie (lista[0]). Słownik (dict) odwołuje się po kluczu:

1
2
3
4
5
6
7
8
osoba = {
    "imie": "Anna",
    "wiek": 32,
    "miasto": "Warszawa",
}

osoba["imie"]        # "Anna"
osoba["zawod"] = "Programistka"   # dodanie nowego klucza

Przydatne metody, które warto znać od razu:

1
2
3
4
5
6
osoba.get("wiek")            # 32
osoba.get("kraj", "Polska")  # "Polska" — wartość domyślna, gdy klucza brak

osoba.keys()      # wszystkie klucze
osoba.values()    # wszystkie wartości
osoba.items()     # pary (klucz, wartość) — najczęściej używane w pętlach
1
2
for klucz, wartosc in osoba.items():
    print(f"{klucz}: {wartosc}")

Słownik może też przechowywać listy, inne słowniki, w zasadzie cokolwiek — to podstawowa struktura, w którą naturalnie pakuje się większość danych ustrukturyzowanych.

Funkcje — argumenty domyślne, *args i **kwargs

Podstawowa funkcja w Pythonie wygląda tak:

1
2
3
4
5
def powitaj(imie, powitanie="Cześć"):
    return f"{powitanie}, {imie}!"

powitaj("Ola")                 # "Cześć, Ola!"
powitaj("Ola", "Dzień dobry")   # "Dzień dobry, Ola!"

Czasem nie wiadomo z góry, ile argumentów funkcja dostanie. Do tego służą *args (dowolna liczba argumentów pozycyjnych, jako krotka) i **kwargs (dowolna liczba argumentów nazwanych, jako słownik):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def zsumuj(*args):
    return sum(args)

zsumuj(1, 2, 3)          # 6
zsumuj(1, 2, 3, 4, 5)    # 15

def opisz(**kwargs):
    for klucz, wartosc in kwargs.items():
        print(f"{klucz} = {wartosc}")

opisz(model="gpt", wersja=4, tryb="test")
# model = gpt
# wersja = 4
# tryb = test

To bardzo częsty wzorzec w bibliotekach: funkcja przyjmuje **kwargs i przekazuje je dalej do innej funkcji, bez wypisywania każdego parametru z osobna.

JSON — słownik zapisany jako tekst

JSON to format tekstowy, który wygląda niemal identycznie jak słownik i lista w Pythonie — i to nieprzypadkowo, bo dane konfiguracyjne, odpowiedzi API czy zapisane ustawienia najczęściej mają właśnie taką postać:

1
2
3
4
5
{
  "imie": "Anna",
  "wiek": 32,
  "zainteresowania": ["python", "szachy"]
}

W Pythonie do pracy z JSON-em służy wbudowany moduł json:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import json

dane = {"imie": "Anna", "wiek": 32}

# słownik -> tekst JSON
tekst = json.dumps(dane, ensure_ascii=False)

# tekst JSON -> słownik
z_powrotem = json.loads(tekst)

# zapis do pliku
with open("dane.json", "w", encoding="utf-8") as plik:
    json.dump(dane, plik, ensure_ascii=False, indent=2)

# odczyt z pliku
with open("dane.json", "r", encoding="utf-8") as plik:
    wczytane = json.load(plik)

Cztery funkcje do zapamiętania: dumps/loads działają na tekście w pamięci, dump/load — na plikach. Nazwa z “s” na końcu (dumps, loads) to zawsze wersja “string”.

Podsumowanie

Słowniki, funkcje z elastyczną liczbą argumentów i format JSON to trzy klocki, bez których trudno się obejść nawet w najprostszym skrypcie — a szczególnie w takim, który będzie się komunikował z czymkolwiek na zewnątrz. W kolejnym wpisie z tej serii przejdziemy do pracy z plikami i obsługi błędów — a stąd już bardzo blisko do pierwszego skryptu wykorzystującego LlamaIndex.