Hierarchia własnych wyjątków

Zadanie 7 z 7 · rozdział 19Trudność: 2 z 3dziedziczeniewyjątkitry-except

Treść zadania

Zdefiniuj własne wyjątki tworzące hierarchię:

  • BladDanych — dziedziczy po wbudowanej klasie Exception; ogólny błąd danych wejściowych,
  • BladFormatu — dziedziczy po BladDanych; dane mają zły format,
  • BladZakresu — dziedziczy po BladDanych; format jest dobry, ale wartość jest spoza dozwolonego zakresu.

Napisz funkcję parsuj_godzine(tekst), która zamienia godzinę zapisaną w postaci GG:MM na liczbę minut od północy ($60 \cdot GG + MM$). Funkcja sprawdza dane w tej kolejności:

  1. Jeśli tekst nie ma dokładnie 5 znaków, na pozycji 2 nie ma dwukropka albo znaki na pozycjach 0, 1, 3, 4 nie są cyframi — zgłasza BladFormatu("oczekiwano formatu GG:MM").
  2. Jeśli godzina jest większa od 23 — zgłasza BladZakresu("godzina spoza zakresu 0-23").
  3. Jeśli minuty są większe od 59 — zgłasza BladZakresu("minuty spoza zakresu 0-59").

Program dla każdej wczytanej linii wywołuje parsuj_godzine i wypisuje wynik albo informację o błędzie. Oba rodzaje błędów przechwytuje jedną klauzulą except BladDanych as e — łapie ona wyjątki klasy BladDanych i wszystkich klas, które po niej dziedziczą.

Dane wejściowe

  • 1. linia: liczba napisów $n$
  • kolejne $n$ linii: napis do sprawdzenia (bez spacji)

Dane wyjściowe

Dla każdego napisu jedna linia:

  • <napis> -> <minuty> — jeśli napis jest poprawny,
  • <napis> -> <NazwaKlasyWyjątku>: <komunikat> — jeśli funkcja zgłosiła wyjątek, np. 24:00 -> BladZakresu: godzina spoza zakresu 0-23.

Ograniczenia

  • $1 \le n \le 50$
  • Każdy napis ma od 1 do 20 znaków.

Uwagi

  • Własny wyjątek to zwykła klasa dziedzicząca po Exception — zwykle nie potrzebuje żadnego kodu: class BladDanych(Exception): pass. Komunikat przekazuje się przy zgłaszaniu: raise BladFormatu("…").
  • Nazwę klasy przechwyconego wyjątku odczytasz wyrażeniem type(e).__name__.
  • Gdy błędy różnych klas trzeba obsłużyć różnie, piszemy kilka klauzul except. Python sprawdza je po kolei i wybiera pierwszą pasującą, dlatego klasy potomne muszą stać przed klasą bazową:
    ```python
    try:
    minuty = parsuj_godzine(tekst)
    except BladFormatu:
    ... # tylko błędy formatu
    except BladDanych:
    ... # wszystkie pozostałe błędy danych (np. BladZakresu)
    `
    Gdyby except BladDanych stało pierwsze, przechwyciłoby także BladFormatu, a druga klauzula nigdy by się nie wykonała.
  • "07".isdigit() sprawdza, czy napis składa się z samych cyfr.

Przykład

Wejście
5
07:30
23:59
24:00
7:30
12:60
Wyjście
07:30 -> 450
23:59 -> 1439
24:00 -> BladZakresu: godzina spoza zakresu 0-23
7:30 -> BladFormatu: oczekiwano formatu GG:MM
12:60 -> BladZakresu: minuty spoza zakresu 0-59
Zasady obowiązujące w rozdziale 19

Zadania w tym rozdziale uczą dziedziczenia: klasa potomna przejmuje atrybuty i metody klasy bazowej, może je nadpisać (override) albo rozszerzyć, wywołując wersję z klasy bazowej przez super(). Dzięki polimorfizmowi ten sam kod (np. pętla po liście obiektów) wywołuje metodę odpowiednią dla konkretnej klasy obiektu. Dziedziczenie przydaje się też przy wyjątkach: własne wyjątki to klasy dziedziczące po Exception, które można układać w hierarchie.

Konwencje wspólne:

  • Każde zadanie to osobny program: czyta standardowe wejście i wypisuje wynik na standardowe wyjście.
  • W każdym zadaniu dostajesz kod startowy ze szkieletami klas i gotowym wczytywaniem danych. Twoim zadaniem jest uzupełnienie klas — wynik programu zależy od tego, jak działają Twoje klasy.
  • Nazwy klas i metod podane w treści są obowiązkowe (kod startowy z nich korzysta). Nazwy w kodzie piszemy bez polskich znaków, np. Kolo, Czlowiek.
  • „Z dokładnością do 2 miejsc po przecinku” oznacza dokładnie dwie cyfry po kropce, np. f"{x:.2f}" (3.00, 4.50).
  • Program nie wypisuje komunikatów typu „Podaj liczbę:”.

Zadanie pochodzi z otwartego zbioru Nauka-Programowania (z rozwiązaniami wzorcowymi). Zgłoś błąd w treści lub testach.

Python uruchomi się w przeglądarce przy pierwszym teście.

Kod zapisuje się automatycznie w tej przeglądarce. Tab wstawia wcięcie; aby opuścić edytor klawiaturą, naciśnij Esc, a potem Tab.

Testy

Program dostaje „Wejście” przez input() i musi wypisać „Oczekiwane wyjście”. Liczby porównywane są z tolerancją 0,01, a tekst podany w input("…") nie jest sprawdzany.

Test 1

Nie uruchomiono
Wejście
1
00:00
Oczekiwane wyjście
00:00 -> 0

Test 2

Nie uruchomiono
Wejście
2
ab:cd
12-30
Oczekiwane wyjście
ab:cd -> BladFormatu: oczekiwano formatu GG:MM
12-30 -> BladFormatu: oczekiwano formatu GG:MM

Test 3

Nie uruchomiono
Wejście
3
99:99
12:345
00:59
Oczekiwane wyjście
99:99 -> BladZakresu: godzina spoza zakresu 0-23
12:345 -> BladFormatu: oczekiwano formatu GG:MM
00:59 -> 59

Test 4

Nie uruchomiono
Wejście
4
13:05
1305
23:60
:1234
Oczekiwane wyjście
13:05 -> 785
1305 -> BladFormatu: oczekiwano formatu GG:MM
23:60 -> BladZakresu: minuty spoza zakresu 0-59
:1234 -> BladFormatu: oczekiwano formatu GG:MM

Test 5

Nie uruchomiono
Wejście
2
12:3a
18:45
Oczekiwane wyjście
12:3a -> BladFormatu: oczekiwano formatu GG:MM
18:45 -> 1125
Uruchom z własnymi danymi