Streszczenie Obsługa wyjątków w OOP - try, except, raise i własne klasy wyjątków

Ten moduł poświęcony jest mechanizmowi wyjątków w Pythonie w kontekście programowania obiektowego. Wyjątki są fundamentem solidnego, odpornego na błędy kodu - pozwalają oddzielić logikę biznesową od obsługi sytuacji nadzwyczajnych bez zaśmiecania kodu setkami warunków if . Zamiast rozsiewać po kodzie dziesiątki instrukcji warunkowych, grupujemy logikę obsługi błędów w jednym miejscu, co radykalnie poprawia czytelność i utrzymywalność projektu. Omówione są bloki try , except , else i finally oraz hierarchia wbudowanych wyjątków od BaseException przez Exception do konkretnych typów ( ZeroDivisionError , TypeError , ValueError , IndexError , KeyError , FileNotFoundError ). Moduł uczy ręcznego zgłaszania wyjątków za pomocą raise , tworzenia własnych klas wyjątków dziedziczących po Exception z własnymi atrybutami, a także łańcuchowania wyjątków przez raise ... from ... . Przedstawione są style LBYL (Look Before You Leap) i EAFP (Easier to Ask for Forgiveness than Permission) oraz dobre praktyki: łapanie konkretnych typów, unikanie gołego except: , poprawne zwalnianie zasobów w finally . Praktyczne przykłady demonstrują kompleksową obsługę błędów w aplikacjach OOP - od walidacji danych w konstruktorach aż po rozbudowane hierarchie własnych klas wyjątków w symulacji bankomatu.

  • Składnia try-except-else-finally - cztery bloki, kolejność wykonania, łapanie wielu typów wyjątków w jednym lub kilku blokach except
  • Hierarchia wyjątków - BaseExceptionException → typy szczegółowe, atrybut __mro__ do badania łańcucha dziedziczenia
  • Rzucanie wyjątków (raise) - ręczne zgłaszanie, ponowne rzucanie w bloku except , łańcuchowanie raise ... from z zachowaniem kontekstu
  • Własne klasy wyjątków - dziedziczenie po Exception , dodawanie atrybutów i kodów błędów, rozbudowa konstruktora
  • Metody rzucające wyjątki w OOP - walidacja argumentów w metodach klas, sygnalizowanie błędnych stanów obiektu
  • Dobre praktyki i style - LBYL vs EAFP, unikanie gołego except: , specyficzność kontra ogólność obsługi, rola finally w zwalnianiu zasobów
  • Łańcuchowanie wyjątków - raise ... from ... z zachowaniem oryginalnego kontekstu błędu przez atrybut __cause__

Slajd zatytułowany "Obsługa wyjątków w OOP - try, except, raise i własne klasy wyjątków" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

1 / 45 Część 11: obsługa wyjątków w OOP

Obsługa wyjątków w Pythonie

W tej części poznamy mechanizm wyjątków w Pythonie - jak je łapać, zgłaszać i tworzyć własne klasy wyjątków. Wyjątki to fundament solidnego kodu w paradygmacie obiektowym - pozwalają budować aplikacje, które elegancko radzą sobie z nieprzewidzianymi sytuacjami bez zakłócenia głównego przepływu programu. Bez wyjątków każda funkcja musiałaby zwracać specjalne wartości oznaczające błąd, co prowadzi do rozwlekłych łańcuchów warunków i trudnego do utrzymania kodu.

Omówimy bloki try , except , else , finally , hierarchię wbudowanych wyjątków oraz technikę tworzenia własnych klas wyjątków dziedziczących po Exception . Na konkretnych przykładach zobaczysz, jak stosować wyjątki w praktyce - od prostego zabezpieczania dzielenia przez zero, przez walidację danych w klasach, aż po rozbudowane hierarchie wyjątków w aplikacjach biznesowych. Każdy przykład jest zaprezentowany w kontekście OOP, ponieważ właśnie w projektach obiektowych wyjątki ujawniają swoją pełną moc.

Slajd zatytułowany "Część 11: obsługa wyjątków w OOP" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

2 / 45Cele dydaktyczne

Czego nauczysz się w tej części?

  • Rozumieć, czym są wyjątki i jak działa mechanizm rzucania i łapania
  • Stosować bloki try , except , else i finally w różnych konfiguracjach
  • Znać hierarchię wbudowanych wyjątków w Pythonie - od BaseException do konkretnych typów
  • Łapać wiele typów wyjątków w jednym lub kilku blokach except
  • Ręcznie zgłaszać wyjątki za pomocą raise z komunikatem lub bez
  • Tworzyć własne klasy wyjątków dziedziczące po Exception
  • Dodawać atrybuty i kody błędów do własnych wyjątków
  • Łańcuchować wyjątki za pomocą raise ... from ... z zachowaniem kontekstu błędu
  • Stosować wyjątki do walidacji w metodach klas (OOP)
  • Projektować hierarchie własnych wyjątków dla aplikacji biznesowych
  • Stosować idiom EAFP (Easier to Ask for Forgiveness than Permission) w kodzie produkcyjnym
  • Używać raise ... from ... do łańcuchowania wyjątków przy przepakowywaniu błędów niskiego poziomu
Cel główny: Pisać kod, który elegancko radzi sobie z błędami dzięki mechanizmowi wyjątków.
Cele dydaktyczne

Przedstawione cele dydaktyczne zostały opracowane zgodnie z zasadą stopniowania trudności, co pozwala na systematyczne budowanie kompetencji. Każdy cel koncentruje się na konkretnym aspekcie programowania obiektowego, od teorii przez praktykę aż po zaawansowane zastosowania. Realizacja wszystkich założeń gwarantuje solidne podstawy do dalszego rozwoju w kierunku bardziej złożonych zagadnień, takich jak wzorce projektowe. Materiał został dostosowany do potrzeb studentów kierunków informatycznych. Oczekuje się, że po ukończeniu modułu student będzie potrafił samodzielnie projektować proste hierarchie klas i implementować je w Pythonie. Regularne sprawdzanie postępów pomoże w identyfikacji obszarów wymagających dodatkowej uwagi i powtórki.

Struktura kursu przewiduje płynne przejście od zagadnień podstawowych do bardziej złożonych, z licznymi przykładami i ćwiczeniami praktycznymi. Zaleca się aktywne uczestnictwo poprzez samodzielne eksperymenty z kodem. Środowisko REPL Pythona jest doskonałym narzędziem do natychmiastowego testowania omawianych koncepcji bez konieczności tworzenia plików projektowych. Warto również korzystać z dodatkowych materiałów, takich jak dokumentacja oficjalna Pythona oraz społecznościowe fora programistyczne. Systematyczna praca i regularne powtórki są kluczem do sukcesu w opanowaniu programowania obiektowego.

3 / 45 Czym są wyjątki - błędy w programach

Błędy zdarzają się zawsze

Podczas działania programu mogą wystąpić różne sytuacje wyjątkowe: dzielenie przez zero, brak pliku, niepoprawny typ danych, próba dostępu do nieistniejącego elementu listy, a nawet problemy sieciowe czy brak pamięci. W żadnej aplikacji nie da się uniknąć wszystkich możliwych błędów - dlatego trzeba umieć je obsługiwać. Doświadczeni programiści wiedzą, że nie chodzi o pisanie kodu bez błędów, lecz o pisanie kodu, który radzi sobie z błędami w przewidywalny i bezpieczny sposób.

Python informuje nas o takich błędach, rzucając wyjątek . Jest to obiekt zawierający informację o typie błędu, jego opis oraz ślad stosu (ang. traceback ), czyli kolejność wywołań funkcji, która doprowadziła do błędu. Jeżeli nie obsłużymy wyjątku, program przerywa działanie i wyświetla tzw. traceback - raport ze stosu wywołań, który pomaga zlokalizować źródło problemu. Im więcej warstw wywołań między miejscem błędu a głównym skryptem, tym dłuższy traceback - ale każda linia zawiera cenne informacje diagnostyczne.

Główne typy błędów:

  • Błąd składni - SyntaxError - wykrywany przed uruchomieniem programu, gdy kod niezgodny ze składnią Pythona
  • Błąd wykonania - np. ZeroDivisionError , TypeError , ValueError - występuje podczas działania programu
  • Błąd logiczny - program działa, ale daje złe wyniki; najtrudniejszy do znalezienia, bo nie generuje wyjątku
  • Błąd zasobów - np. MemoryError , RecursionError - występuje, gdy środowisko wykonawcze nie może sprostać żądaniom programu
Warto wiedzieć: Wyjątki w Pythonie są obiektami - każdy wyjątek to instancja klasy dziedziczącej po BaseException . Dzięki temu możemy je tworzyć, przechowywać i modyfikować jak zwykłe obiekty.
Błędy w programach

Slajd zatytułowany "Czym są wyjątki - błędy w programach" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

4 / 45 Kod: błąd dzielenia przez zero

Dzielenie przez zero - pierwszy wyjątek

# Dzielenie przez zero powoduje ZeroDivisionError

def dziel(a, b):

    return a / b



# Wywołanie z b = 0 - program się zatrzyma

wynik = dziel(10, 0)

# Traceback (most recent call last):

#   File "example.py", line 5, in <module>

#     wynik = dziel(10, 0)

#   File "example.py", line 2, in dziel

#     return a / b

# ZeroDivisionError: division by zero



# Inne operacje, które dają podobne błędy:

# print(10 // 0)   # ZeroDivisionError: integer division or modulo by zero

# print(10 % 0)    # ZeroDivisionError: integer division or modulo by zero

Python natychmiast przerywa działanie i zgłasza wyjątek ZeroDivisionError . W tracebacku widzimy dokładnie, w której linii wystąpił błąd i jaka była ścieżka wywołań. Program bez odpowiedniej obsługi kończy się błędem. Zwróć uwagę, że nie tylko dzielenie ( / ), ale też dzielenie całkowite ( // ) i reszta z dzielenia ( % ) rzucają ten sam wyjątek przy dzielniku równym zero. To ważna lekcja: różne operacje matematyczne mogą prowadzić do tego samego typu wyjątku, więc łapiąc ZeroDivisionError zabezpieczasz się przed całą rodziną podobnych błędów arytmetycznych. W kodzie produkcyjnym warto rozważyć łapanie szerszego ArithmeticError , jeśli zależy nam na obsłudze wszystkich błędów arytmetycznych.

ZeroDivisionError

Błędy są naturalną i nieodłączną częścią procesu uczenia się programowania. Każdy, nawet najbardziej doświadczony programista, popełnia błędy na co dzień - kluczowa jest umiejętność ich szybkiego identyfikowania i poprawiania. Przedstawione na tym slajdzie typowe pomyłki zostały zebrane na podstawie wieloletnich doświadczeń nauczycieli programowania i występują u większości początkujących. Zapamiętanie ich i zrozumienie przyczyn pomoże Ci uniknąć frustracji i straconego czasu na debugowanie. Warto również zapoznać się z technikami debugowania, takimi jak użycie print(), logging czy debuggera wbudowanego w IDE. Świadomość typowych pułapek to pierwszy krok do ich unikania.

Nowoczesne edytory kodu i IDE oferują wiele narzędzi pomagających w wykrywaniu błędów jeszcze przed uruchomieniem programu. PyCharm, VS Code z wtyczką Python, a nawet zaawansowane edytory tekstu z obsługą lintingu potrafią ostrzegać przed wieloma typowymi pomyłkami w czasie rzeczywistym. Korzystanie z type hintów, narzędzi takich jak mypy do statycznej analizy typów oraz systemów CI/CD z automatycznym uruchamianiem testów znacząco redukuje liczbę błędów w kodzie produkcyjnym. Warto od początku nauki wyrobić sobie nawyk korzystania z tych narzędzi, ponieważ znacząco podnoszą one jakość i niezawodność tworzonego oprogramowania.

5 / 45 Kod: błąd indeksowania listy

Indeks spoza zakresu i inne typowe błędy

# Próba dostępu do nieistniejącego indeksu

dane = [1, 2, 3]

print(dane[5])

# Traceback (most recent call last):

#   ...

# IndexError: list index out of range



# To samo dotyczy krotek i stringów

# print((1, 2, 3)[10])  # IndexError: tuple index out of range

# print("Python"[20])    # IndexError: string index out of range
# TypeError - niekompatybilne typy

print("Liczba: " + 42)

# TypeError: can only concatenate str (not "int") to str



# ValueError - niepoprawna wartość do konwersji

int("abc")

# ValueError: invalid literal for int() with base 10: 'abc'



# KeyError - brak klucza w słowniku

print({"a": 1}["b"])

# KeyError: 'b'

Każdy z tych błędów to wyjątek określonego typu, który możemy przechwycić i obsłużyć. Zwróć uwagę, że IndexError występuje nie tylko dla list, ale też dla krotek i napisów - wszystkich sekwencji indeksowanych liczbami. Podobnie KeyError dotyczy słowników, a TypeError pojawia się przy próbie wykonania operacji na niezgodnych typach - na przykład dodawania napisu do liczby. Znajomość tych różnic jest kluczowa, ponieważ precyzyjne łapanie konkretnego typu wyjątku to podstawa dobrego stylu - łapiesz dokładnie to, co może pójść nie tak, a nie wszystko jak leci.

IndexError i inne

Przechowywanie obiektów w kolekcjach, takich jak listy, słowniki czy zbiory, jest podstawowym wzorcem w programowaniu obiektowym. Listy obiektów pozwalają na zbiorcze operacje, takie jak iterowanie, filtrowanie, sortowanie czy agregowanie danych. Python oferuje bogaty zestaw narzędzi do pracy z listami, w tym wyrażenia listowe, funkcje sorted(), filter() oraz sortowanie z kluczem lambda. Ważne jest zrozumienie, że lista przechowuje referencje do obiektów, a nie ich kopie, co ma wpływ na modyfikację danych przez różne części programu. Iterowanie po liście obiektów i wywoływanie ich metod to jeden z najczęstszych wzorców w codziennej pracy.

Kompozycja, czyli umieszczanie jednych obiektów wewnątrz innych, jest podstawową techniką budowania złożonych systemów z prostszych komponentów. W przeciwieństwie do dziedziczenia, które wyraża relację 'jest', kompozycja wyraża relację 'ma' i jest często preferowanym podejściem w projektowaniu obiektowym. Graf obiektów w rzeczywistych systemach może być bardzo złożony, ale nawigacja po nim jest naturalna i czytelna dzięki notacji kropkowej. Kompozycja pozwala na elastyczne budowanie funkcjonalności poprzez łączenie prostych obiektów w bardziej złożone struktury. Wzorzec ten jest fundamentem takich koncepcji jak wstrzykiwanie zależności czy architektura warstwowa.

6 / 45 Co to znaczy "rzucić wyjątek"

Mechanizm działania wyjątków

Gdy Python napotyka błąd, rzuca (ang. raise ) obiekt wyjątku. Program natychmiast opuszcza bieżący kontekst i szuka bloku except , który pasuje do tego wyjątku. Szukanie odbywa się najpierw w bieżącej funkcji, potem w funkcji wywołującej, i tak dalej w górę stosu wywołań.

Jeżeli taki blok istnieje - wykonuje się kod naprawczy. Jeśli nie - wyjątek wędruje w górę stosu wywołań aż do poziomu globalnego, przerywając po drodze działanie każdej funkcji. Wtedy Python wyświetla traceback i kończy program. Ten proces nazywamy rozwijaniem stosu (ang. stack unwinding ). Dzięki tej właściwości nie musimy łapać wyjątków na każdej pośredniej warstwie - możemy przetrzymać obsługę na odpowiednim poziomie abstrakcji, np. w głównej pętli programu.

Metafora: "rzucenie wyjątku" = sygnalizacja, że coś poszło nie tak. "Łapanie wyjątku" = obsługa tej sytuacji. Można też ponownie rzucić wyjątek za pomocą gołego raise , co pozwala na częściową obsługę i przekazanie błędu wyżej.
Rzucanie wyjątku

Programowanie obiektowe wywodzi się z języka Simula z lat 60. XX wieku, a jego rozwój przyspieszył w latach 70. wraz z językiem Smalltalk, który wprowadził wiele koncepcji używanych do dziś, takich jak klasy, metody i dziedziczenie. Współcześnie OOP jest wspierane przez większość popularnych języków programowania, choć każdy z nich implementuje ten paradygmat nieco inaczej. Python przyjął podejście pragmatyczne, w którym wszystko jest obiektem, ale programista nie jest zmuszany do obiektowego stylu. Dzięki temu Python jest językiem wieloparadygmatowym, łączącym OOP z programowaniem proceduralnym i funkcyjnym w elastyczny sposób. Zrozumienie genezy i ewolucji OOP pomaga docenić jego zalety i świadomie stosować go we własnych projektach programistycznych.

Cztery filary OOP - enkapsulacja, dziedziczenie, polimorfizm i abstrakcja - są ze sobą ściśle powiązane i wzajemnie się uzupełniają. Enkapsulacja chroni stan obiektu przed niekontrolowanym dostępem z zewnątrz, co zwiększa bezpieczeństwo i spójność danych. Dziedziczenie pozwala na budowanie hierarchii klas i wielokrotne wykorzystanie kodu bez jego kopiowania. Polimorfizm umożliwia jednolity interfejs dla różnych typów obiektów, co upraszcza projektowanie rozszerzalnych systemów. Abstrakcja koncentruje się na istotnych cechach, pomijając nieistotne szczegóły implementacyjne. Opanowanie tych czterech koncepcji stanowi fundament biegłości w OOP.

7 / 45 Podstawowa składnia try-except

Struktura bloków - cztery elementy składowe

Python udostępnia cztery słowa kluczowe do obsługi wyjątków, które można łączyć w jeden spójny mechanizm. Dzięki tej elastyczności możemy precyzyjnie sterować przepływem sterowania w sytuacjach wyjątkowych - inaczej reagować na błąd, a inaczej na sukces, a przy tym zawsze wykonać niezbędne operacje porządkowe.

  • try - blok, w którym może wystąpić błąd; obejmuje potencjalnie niebezpieczny kod
  • except - blok obsługi błędu (może być wiele); wykonuje się tylko gdy wystąpi wyjątek danego typu
  • else - blok wykonywany tylko wtedy, gdy blok try nie rzucił wyjątku
  • finally - blok wykonywany zawsze, niezależnie od tego, czy był błąd (idealny do zwalniania zasobów)
try:

    # kod, który może rzucić wyjątek

except TypWyjątku:

    # obsługa błędu - tylko gdy wystąpi wyjątek tego typu

else:

    # gdy nie było błędu - opcjonalne

finally:

    # zawsze się wykonuje - opcjonalne
Uwaga: Kolejność bloków jest wymuszona: najpierw try , potem jeden lub więcej except , potem opcjonalnie else , na końcu opcjonalnie finally . Nie można zmienić tej kolejności.
Składnia try-except

Slajd zatytułowany "Podstawowa składnia try-except" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

8 / 45 Kod: try-except – łapanie błędu

Łapanie ZeroDivisionError - pierwszy bezpieczny kod

try:

    a = 10

    b = 0

    wynik = a / b

    print("Wynik:", wynik)

except ZeroDivisionError:

    print("Nie dziel przez zero!")



# Output: Nie dziel przez zero!



# Program kontynuuje działanie po obsłużonym wyjątku

print("Program działa dalej!")

# Output: Program działa dalej!

Gdy pojawi się ZeroDivisionError , program nie przerywa działania - wykonuje się kod w bloku except , a następnie program kontynuuje pracę od pierwszego wiersza poza całą konstrukcją try-except . Dzięki temu możemy utrzymać działanie programu nawet w przypadku wystąpienia błędu. Zauważ, że linijka print("Wynik:", wynik) nie zostanie wykonana, ponieważ wyjątek został rzucony wcześniej. Dla porównania - bez bloku try program zakończyłby się z tracebackiem i całe działanie byłoby przerwane. To właśnie jest główna wartość dodawana przez obsługę wyjątków: odzyskiwanie kontroli i kontynuacja działania.

try-except

Slajd zatytułowany "Kod: try-except – łapanie błędu" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

9 / 45 Kod: else – gdy nie ma błędu

Blok else wykonuje się przy braku wyjątku

try:

    a = 10

    b = 2

    wynik = a / b

except ZeroDivisionError:

    print("Nie dziel przez zero!")

else:

    print("Wynik dzielenia:", wynik)



# Output: Wynik dzielenia: 5.0

Blok else uruchamia się tylko wtedy, gdy blok try nie rzucił żadnego wyjątku. To właściwe miejsce na kod, który zależy od pomyślnego wykonania. Dzięki else unikamy sytuacji, w której kod sukcesu sąsiaduje z kodem potencjalnie niebezpiecznym wewnątrz try - poprawia to czytelność i precyzję intencji: w try umieszczamy tylko operacje, które mogą rzucić wyjątek, a resztę obsługi sukcesu przenosimy do else .

Blok else

Slajd zatytułowany "Kod: else – gdy nie ma błędu" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

10 / 45 Kod: finally – zawsze wykonane

Blok finally wykonuje się zawsze

try:

    plik = open("dane.txt", "r")

    dane = plik.read()

    print(dane)

except FileNotFoundError:

    print("Plik nie istnieje.")

finally:

    print("Zamykanie pliku (jeśli otwarty).")

    try:

        plik.close()

    except NameError:

        pass



# finally wykona się niezależnie od tego, czy był błąd

finally jest idealny do zwalniania zasobów - zamykania plików, połączeń sieciowych itp. Gwarancja wykonania dotyczy również sytuacji, gdy w bloku try wystąpi instrukcja return , break lub continue - finally i tak się wykona. To właśnie dzięki tej gwarancji finally jest preferowanym miejscem do zamykania plików, zwalniania blokad czy zamykania połączeń sieciowych. W nowoczesnym Pythonie często zastępujemy go menedżerem kontekstu with , ale nadal istnieje wiele scenariuszy, w których finally jest niezastąpiony.

Blok finally

Slajd zatytułowany "Kod: finally – zawsze wykonane" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

11 / 45 Kod: wszystkie cztery bloki

Kompletny przykład

def podziel_i_wypisz(a, b):

    try:

        wynik = a / b

    except ZeroDivisionError:

        print("Błąd: dzielenie przez zero.")

    except TypeError:

        print("Błąd: podaj liczby.")

    else:

        print("Wynik:", wynik)

    finally:

        print("Koniec próby dzielenia.")



podziel_i_wypisz(10, 2)

podziel_i_wypisz(10, 0)

podziel_i_wypisz(10, "a")

Ten przykład pokazuje wszystkie cztery bloki w akcji w ramach jednej funkcji. Dzięki rozdzieleniu bloków except dla ZeroDivisionError i TypeError każdy rodzaj błędu otrzymuje inną odpowiedź. Blok else wyświetla wynik tylko po udanym dzieleniu, natomiast finally informuje o zakończeniu próby niezależnie od wyniku. Jest to wzorzec godny naśladowania: precyzyjne łapanie konkretnych typów, jasny podział odpowiedzialności między blokami i gwarancja wykonania kodu porządkowego.

Cztery bloki

Podsumowanie to dobry moment na refleksję nad przyswojonym materiałem i identyfikację obszarów wymagających dodatkowej pracy. Wymienione punkty stanowią esencję przerobionej części kursu - od definicji klasy, przez tworzenie obiektów, aż po kompozycję i wzorzec fabryki. Każdy z tych punktów będzie rozwijany w kolejnych modułach, dlatego warto upewnić się, że są dobrze zrozumiane. Zachęcamy do tworzenia własnych notatek i map myśli, które pomagają w usystematyzowaniu wiedzy. Regularne powtórki są kluczowe dla trwałego zapamiętania materiału.

Mapy myśli są skutecznym narzędziem wizualizacji złożonych koncepcji i relacji między nimi. Przedstawiona mapa obrazuje najważniejsze pojęcia omówione w tej części kursu oraz ich wzajemne powiązania. Tworzenie własnych map myśli podczas nauki programowania aktywuje inne obszary mózgu niż czytanie liniowego tekstu, co przekłada się na lepsze zapamiętywanie. Studenci, którzy regularnie tworzą mapy myśli, osiągają lepsze wyniki w testach koncepcyjnych i szybciej łączą nowe informacje z już posiadaną wiedzą. Zachęcamy do wykorzystania tej techniki.

12 / 45 Podsumowanie składni

Zasady użycia bloków

  • try jest wymagany - bez niego nie można użyć except , else ani finally
  • Może być wiele bloków except dla różnych typów wyjątków
  • else i finally są opcjonalne
  • finally wykonuje się ZAWSZE - nawet gdy w try jest return
  • Kolejność: tryexcept (jeden lub więcej) → elsefinally
  • else nie wykona się, jeśli któryś z bloków except rzuci własny wyjątek - podobnie finally wykona się przed opuszczeniem funkcji, nawet przy return
Wskazówka: Nie używaj gołego except: (bez typu) - łapie absolutnie wszystko, w tym KeyboardInterrupt i SystemExit .
Podsumowanie składni

Podsumowanie to dobry moment na refleksję nad przyswojonym materiałem i identyfikację obszarów wymagających dodatkowej pracy. Wymienione punkty stanowią esencję przerobionej części kursu - od definicji klasy, przez tworzenie obiektów, aż po kompozycję i wzorzec fabryki. Każdy z tych punktów będzie rozwijany w kolejnych modułach, dlatego warto upewnić się, że są dobrze zrozumiane. Zachęcamy do tworzenia własnych notatek i map myśli, które pomagają w usystematyzowaniu wiedzy. Regularne powtórki są kluczowe dla trwałego zapamiętania materiału.

Mapy myśli są skutecznym narzędziem wizualizacji złożonych koncepcji i relacji między nimi. Przedstawiona mapa obrazuje najważniejsze pojęcia omówione w tej części kursu oraz ich wzajemne powiązania. Tworzenie własnych map myśli podczas nauki programowania aktywuje inne obszary mózgu niż czytanie liniowego tekstu, co przekłada się na lepsze zapamiętywanie. Studenci, którzy regularnie tworzą mapy myśli, osiągają lepsze wyniki w testach koncepcyjnych i szybciej łączą nowe informacje z już posiadaną wiedzą. Zachęcamy do wykorzystania tej techniki.

13 / 45 Hierarchia wyjątków - BaseException → Exception → ...

Drzewo dziedziczenia wyjątków

Wszystkie wyjątki w Pythonie są klasami dziedziczącymi po BaseException . Główna gałąź to Exception , po której dziedziczą wszystkie standardowe błędy programu. Podział na BaseException i Exception nie jest przypadkowy - te pierwsze (jak SystemExit czy KeyboardInterrupt ) są przeznaczone dla mechanizmów systemowych i prawie nigdy nie powinny być łapane przez kod aplikacji. Właśnie dlatego gołe except: jest tak niebezpieczne - łapie również te wyjątki systemowe.

BaseException

 +-- SystemExit

 +-- KeyboardInterrupt

 +-- GeneratorExit

 +-- Exception

      +-- StopIteration

      +-- ArithmeticError

      |    +-- ZeroDivisionError

      +-- LookupError

      |    +-- IndexError

      |    +-- KeyError

      +-- ValueError

      +-- TypeError

      +-- OSError

      +-- itd.
Hierarchia wyjątków

Slajd zatytułowany "Hierarchia wyjątków - BaseException → Exception → ..." przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

14 / 45 Kod: sprawdzanie hierarchii

Sprawdzanie, czy wyjątek jest podklasą

# Użycie issubclass do sprawdzenia hierarchii

print(issubclass(ZeroDivisionError, ArithmeticError))

# True



print(issubclass(ZeroDivisionError, Exception))

# True



print(issubclass(ZeroDivisionError, BaseException))

# True



print(issubclass(ValueError, ArithmeticError))

# False - ValueError nie jest błędem arytmetycznym



print(issubclass(ValueError, Exception))

# True - ale dziedziczy po Exception

Funkcja issubclass przyjmuje dwa argumenty - potencjalną podklasę i potencjalną nadklasę - i zwraca True , jeśli pierwsza jest podklasą drugiej. Dzięki temu możemy dynamicznie sprawdzać relacje w hierarchii wyjątków. Przykład z ValueError i ArithmeticError pokazuje, że nie wszystkie wyjątki dziedziczą po ArithmeticError - mimo że oba są podklasami Exception . To pozwala projektować własne hierarchie wyjątków z logicznymi grupami.

Quiz podsumowujący to nie tylko sprawdzenie wiedzy, ale także okazja do utrwalenia najważniejszych koncepcji poprzez aktywne przypominanie sobie materiału. Badania z zakresu neurodydaktyki pokazują, że testowanie własnej wiedzy jest jedną z najskuteczniejszych metod uczenia się, znacznie efektywniejszą niż bierne czytanie. Każde pytanie quizu zostało starannie zaprojektowane, aby sprawdzić zrozumienie konkretnego zagadnienia, a nie tylko pamięciowe odtworzenie definicji. Jeżeli któreś pytanie sprawiło Ci trudność, potraktuj to jako sygnał, że dany temat wymaga powtórzenia. Wróć do odpowiedniego slajdu i przeanalizuj go jeszcze raz, tym razem zwracając uwagę na szczegóły, które mogły Ci umknąć.

Sukces w nauce programowania polega na systematycznym budowaniu wiedzy - każda kolejna część opiera się na fundamentach z części poprzednich. Jeżeli masz wątpliwości co do którejkolwiek koncepcji, nie przechodź dalej, dopóki jej nie wyjaśnisz. Wykorzystaj dostępne zasoby: dokumentację Pythona, fora społecznościowe, tutoriale wideo i oczywiście możliwość eksperymentowania we własnym środowisku programistycznym. Pamiętaj, że każdy zaawansowany programista zaczynał od podstaw i pokonał te same trudności co Ty teraz. Gratulujemy ukończenia kolejnego etapu nauki i życzymy powodzenia w dalszej części kursu.

15 / 45 Kod: __mro__ wyjątku

Kolejność rozwiązywania metod (MRO) wyjątku

Każda klasa w Pythonie ma atrybut __mro__ (Method Resolution Order), który pokazuje kolejność dziedziczenia.

print(ZeroDivisionError.__mro__)

# (<class 'ZeroDivisionError'>,

#  <class 'ArithmeticError'>,

#  <class 'Exception'>,

#  <class 'BaseException'>,

#  <class 'object'>)



print(IndexError.__mro__)

# (<class 'IndexError'>,

#  <class 'LookupError'>,

#  <class 'Exception'>,

#  <class 'BaseException'>,

#  <class 'object'>)

Atrybut __mro__ pokazuje krotkę klas w kolejności, w jakiej Python przeszukuje je przy rozwiązywaniu metod i przy dopasowywaniu wyjątków w blokach except . Dzięki temu widzimy, że ZeroDivisionError przechodzi przez ArithmeticErrorExceptionBaseExceptionobject . Oznacza to, że łapiąc ArithmeticError , łapiemy również ZeroDivisionError . Znajomość __mro__ jest szczególnie przydatna przy własnych hierarchiach wyjątków, gdy chcemy przewidzieć, które bloki except zostaną dopasowane.

MRO wyjątku

Slajd zatytułowany "Kod: __mro__ wyjątku" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

16 / 45 Kod: TypeError, ValueError, IndexError

Typowe wyjątki w praktyce

# TypeError – niekompatybilny typ

try:

    wynik = "text" + 123

except TypeError as e:

    print("TypeError:", e)



# ValueError – niepoprawna wartość

try:

    liczba = int("nie_liczba")

except ValueError as e:

    print("ValueError:", e)



# IndexError – indeks spoza zakresu

try:

    lista = [1, 2, 3]

    elem = lista[10]

except IndexError as e:

    print("IndexError:", e)

Każdy z tych trzech przykładów demonstruje łapanie innego typu wyjątku z użyciem składni as e , dzięki której przechwytujemy obiekt wyjątku i wyświetlamy jego komunikat. Konstrukcja except ... as e jest szczególnie przydatna, gdy chcemy zalogować dokładny komunikat błędu lub przekazać go dalej. W każdym przypadku program kontynuuje działanie po obsłużonym wyjątku - to właśnie jest istota odpornego kodu.

Typowe wyjątki

Slajd zatytułowany "Kod: TypeError, ValueError, IndexError" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

17 / 45 Podsumowanie hierarchii

Co warto zapamiętać?

  • Wszystkie wyjątki dziedziczą po BaseException
  • Własne wyjątki tworzymy przez dziedziczenie po Exception
  • Łapiąc wyjątek nadrzędny (łapiemy również wszystkie podrzędne)
  • Kolejność bloków except ma znaczenie - najpierw szczegółowe, potem ogólne
  • __mro__ pokazuje pełną ścieżkę dziedziczenia klasy
  • Nie łap wyjątków, których nie jesteś w stanie obsłużyć - pozwól im propagować wyżej
Zasada: Łap wyjątki tak wąsko, jak to możliwe - unikaj gołego except: .

Podsumowanie to dobry moment na refleksję nad przyswojonym materiałem i identyfikację obszarów wymagających dodatkowej pracy. Wymienione punkty stanowią esencję przerobionej części kursu - od definicji klasy, przez tworzenie obiektów, aż po kompozycję i wzorzec fabryki. Każdy z tych punktów będzie rozwijany w kolejnych modułach, dlatego warto upewnić się, że są dobrze zrozumiane. Zachęcamy do tworzenia własnych notatek i map myśli, które pomagają w usystematyzowaniu wiedzy. Regularne powtórki są kluczowe dla trwałego zapamiętania materiału.

Mapy myśli są skutecznym narzędziem wizualizacji złożonych koncepcji i relacji między nimi. Przedstawiona mapa obrazuje najważniejsze pojęcia omówione w tej części kursu oraz ich wzajemne powiązania. Tworzenie własnych map myśli podczas nauki programowania aktywuje inne obszary mózgu niż czytanie liniowego tekstu, co przekłada się na lepsze zapamiętywanie. Studenci, którzy regularnie tworzą mapy myśli, osiągają lepsze wyniki w testach koncepcyjnych i szybciej łączą nowe informacje z już posiadaną wiedzą. Zachęcamy do wykorzystania tej techniki.

18 / 45 Łapanie wielu typów - różne błędy, różne reakcje

Dwa podejścia do wielu wyjątków

Możemy łapać wiele typów wyjątków na dwa sposoby:

  1. Krotka typów - ten sam kod obsługi dla różnych wyjątków: except (TypeError, ValueError):
  2. Osobne bloki - inna reakcja na każdy typ: except TypeError: ... except ValueError: ...

Wybór zależy od tego, czy chcemy reagować tak samo, czy inaczej na poszczególne błędy. W praktyce często stosuje się kombinację obu podejść: najpierw wąskie bloki except dla typów, które wymagają specyficznej reakcji, a na końcu ogólny except Exception jako zabezpieczenie na wszystkie inne przypadki. Ważne jest, by bloki szczegółowe umieszczać przed ogólnymi - Python dopasowuje pierwszy pasujący blok.

Wiele typów

Slajd zatytułowany "Łapanie wielu typów - różne błędy, różne reakcje" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

19 / 45 Kod: except (TypeError, ValueError)

Wiele typów, jedna obsługa

def konwertuj(wartosc):

    try:

        liczba = int(wartosc)

        print("Liczba:", liczba)

    except (ValueError, TypeError) as e:

        print("Błąd konwersji:", e)



konwertuj("123")       # OK

konwertuj("abc")       # ValueError

konwertuj([1, 2])     # TypeError

Używamy krotki w nawiasie - except (TypeError, ValueError): . Zarówno TypeError jak i ValueError zostaną obsłużone w ten sam sposób. To oszczędza miejsce i zapobiega powielaniu kodu, gdy różne typy błędów wymagają identycznej reakcji. Pamiętaj jednak, że użycie krotki ma sens tylko wtedy, gdy obsługa jest rzeczywiście taka sama - w przeciwnym razie lepiej rozdzielić bloki.

Krotka typów

Slajd zatytułowany "Kod: except (TypeError, ValueError)" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

20 / 45 Kod: osobne bloki except

Różne typy, różne reakcje

def analizuj_dane(dane, indeks):

    try:

        wartosc = dane[indeks]

        wynik = 100 / wartosc

        print("Wynik:", wynik)

    except IndexError:

        print("Indeks poza zakresem!")

    except ZeroDivisionError:

        print("Nie można dzielić przez zero!")

    except TypeError:

        print("Nieprawidłowy typ danych!")



analizuj_dane([10, 0, "x"], 1)  # ZeroDivisionError

analizuj_dane([10, 0, "x"], 5)  # IndexError

analizuj_dane([10, 0, "x"], 2)  # TypeError

Funkcja analizuj_dane ilustruje obsługę trzech różnych typów błędów, które mogą wystąpić podczas pracy z listą danych. Dzięki osobnym blokom except każdy błąd otrzymuje odpowiednią wiadomość. Zwróć uwagę, że użycie trzech różnych bloków jest tu lepsze niż krotka typów, ponieważ reakcja na każdy błąd jest inna - chcemy wiedzieć, co dokładnie poszło nie tak.

Osobne bloki except

Podsumowanie to dobry moment na refleksję nad przyswojonym materiałem i identyfikację obszarów wymagających dodatkowej pracy. Wymienione punkty stanowią esencję przerobionej części kursu - od definicji klasy, przez tworzenie obiektów, aż po kompozycję i wzorzec fabryki. Każdy z tych punktów będzie rozwijany w kolejnych modułach, dlatego warto upewnić się, że są dobrze zrozumiane. Zachęcamy do tworzenia własnych notatek i map myśli, które pomagają w usystematyzowaniu wiedzy. Regularne powtórki są kluczowe dla trwałego zapamiętania materiału.

Mapy myśli są skutecznym narzędziem wizualizacji złożonych koncepcji i relacji między nimi. Przedstawiona mapa obrazuje najważniejsze pojęcia omówione w tej części kursu oraz ich wzajemne powiązania. Tworzenie własnych map myśli podczas nauki programowania aktywuje inne obszary mózgu niż czytanie liniowego tekstu, co przekłada się na lepsze zapamiętywanie. Studenci, którzy regularnie tworzą mapy myśli, osiągają lepsze wyniki w testach koncepcyjnych i szybciej łączą nowe informacje z już posiadaną wiedzą. Zachęcamy do wykorzystania tej techniki.

21 / 45 Kod: ogólny except Exception

Łapanie wszystkich wyjątków

def bezpieczne_wykonanie(funkcja, *args):

    try:

        return funkcja(*args)

    except Exception as e:

        print("Wystąpił błąd:", type(e).__name__, "-", e)

        return None



# Testowanie

print(bezpieczne_wykonanie(lambda a, b: a / b, 10, 0))

print(bezpieczne_wykonanie(int, "abc"))

print(bezpieczne_wykonanie(lambda lst: lst[5], [1, 2]))

except Exception łapie wszystkie standardowe wyjątki (ale nie SystemExit czy KeyboardInterrupt ). Ta funkcja bezpieczne_wykonanie jest przykładem uniwersalnego opakowania - przyjmuje dowolną funkcję i jej argumenty, próbuje ją wykonać, a w razie błędu zwraca None . To wzorzec przydatny w sytuacjach, gdy pojedyncza porażka nie powinna przerywać całego procesu, np. podczas przetwarzania wsadowego plików. Użycie except Exception zamiast gołego except: jest bezpieczniejsze, bo przepuszcza wyjątki systemowe.

Ogólny except

Slajd zatytułowany "Kod: ogólny except Exception" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

22 / 45 raise - ręczne zgłaszanie wyjątków

Nie tylko łapiemy, ale też rzucamy

Python pozwala ręcznie zgłaszać wyjątki za pomocą słowa kluczowego raise . To kluczowe w walidacji danych i sygnalizowaniu błędnych stanów. W odróżnieniu od języków takich jak C czy Java, gdzie błędy sygnalizuje się kodami powrotu, Python zachęca do używania wyjątków jako głównego mechanizmu raportowania problemów.

Składnia:

  • raise NazwaWyjątku- rzuca wyjątek bez komunikatu
  • raise NazwaWyjątku("komunikat")- z komunikatem
  • raise - ponownie rzuca aktualny wyjątek (używane w bloku except )
  • raise NowyWyjątek("msg") from stary - łańcuchowanie z zachowaniem kontekstu oryginalnego błędu
raise

Slajd zatytułowany "raise - ręczne zgłaszanie wyjątków" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

23 / 45 Kod: raise ValueError

Rzucanie ValueError

def sprawdz_wiek(wiek):

    if wiek < 0:

        raise ValueError

    print("Wiek:", wiek)



# Wywołanie bez try - program się zatrzyma

# sprawdz_wiek(-5)

# Traceback: ValueError



# Bezpieczne wywołanie

try:

    sprawdz_wiek(-5)

except ValueError:

    print("Wiek nie może być ujemny!")

Sam raise ValueError rzuca wyjątek bez żadnego dodatkowego opisu. To minimalistyczna forma - czasem wystarczy sam typ wyjątku, by przekazać informację o rodzaju błędu. W większości przypadków warto jednak dodać komunikat, który ułatwi debugowanie. Zauważ, że jeśli nie łapiemy wyjątku w bloku try , program zatrzymuje się z odpowiednim tracebackiem - dlatego każde raise powinno być świadomą decyzją projektową.

raise ValueError

Slajd zatytułowany "Kod: raise ValueError" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

24 / 45 Kod: raise z własnym komunikatem

Komunikat w wyjątku

def loguj_sie(login, haslo):

    if len(login) < 3:

        raise ValueError("Login musi mieć co najmniej 3 znaki.")

    if len(haslo) < 6:

        raise ValueError("Hasło musi mieć co najmniej 6 znaków.")

    print("Logowanie udane!")



try:

    loguj_sie("ab", "haslo123")

except ValueError as e:

    print("Błąd:", e)



# Output: Błąd: Login musi mieć co najmniej 3 znaki.

Funkcja loguj_sie to realistyczny przykład walidacji danych wejściowych z użyciem raise . Każdy warunek sprawdza inny aspekt poprawności - długość loginu i hasła. Dzięki opisowym komunikatom osoba wywołująca funkcję (lub użytkownik aplikacji) dokładnie wie, co poszło nie tak. To dobra praktyka: komunikaty wyjątków powinny być zrozumiałe dla programisty i, w miarę możliwości, dla użytkownika.

raise z komunikatem

Slajd zatytułowany "Kod: raise z własnym komunikatem" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

25 / 45 Kod: raise TypeError z warunkiem

Sprawdzanie typu argumentów

def policz_srednia(liczby):

    if not isinstance(liczby, (list, tuple)):

        raise TypeError("Argument musi być listą lub krotką.")

    if len(liczby) == 0:

        raise ValueError("Lista nie może być pusta.")

    return sum(liczby) / len(liczby)



try:

    print(policz_srednia("nie lista"))

except TypeError as e:

    print(e)



try:

    print(policz_srednia([]))

except ValueError as e:

    print(e)

Funkcja policz_srednia pokazuje, jak łączyć sprawdzanie typu ( isinstance ) z walidacją wartości. Dwa różne warunki rzucają dwa różne typy wyjątków: TypeError , gdy argument ma zły typ, i ValueError , gdy lista jest pusta. To rozróżnienie pozwala wywołującemu dostosować obsługę do konkretnego rodzaju błędu - inaczej zareaguje na zły typ argumentu, a inaczej na pustą listę.

Slajd zatytułowany "Kod: raise TypeError z warunkiem" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

26 / 45 Własna klasa wyjątku - dziedziczenie po Exception

Tworzenie własnych wyjątków

W paradygmacie obiektowym często tworzymy własne klasy wyjątków, które są specyficzne dla naszej domeny. Dzięki dziedziczeniu możemy budować hierarchie wyjątków odzwierciedlające strukturę biznesową aplikacji - na przykład BladAplikacjiBladBazyDanych , BladSieci .

Wystarczy utworzyć klasę dziedziczącą po Exception:

class MojWyjatek(Exception):

    pass

To wszystko! Taka klasa ma już wszystkie podstawowe funkcjonalności wyjątku. Możemy ją rozwijać, dodając własne metody i atrybuty.

Własny wyjątek

Slajd zatytułowany "Własna klasa wyjątku - dziedziczenie po Exception" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

27 / 45 Kod: prosta własna klasa wyjątku

Najprostszy własny wyjątek

# Definicja własnej klasy wyjątku

class BladMatematyczny(Exception):

    pass



# Użycie

def pierwiastek(x):

    if x < 0:

        raise BladMatematyczny("Nie ma pierwiastka z liczby ujemnej.")

    return x ** 0.5



try:

    print(pierwiastek(-4))

except BladMatematyczny as e:

    print("Wystąpił błąd matematyczny:", e)

Klasa BladMatematyczny dziedziczy po Exception i działa jak każdy standardowy wyjątek. Mimo że definicja klasy zawiera tylko pass , dzięki dziedziczeniu otrzymuje ona wszystkie podstawowe mechanizmy: konstruktor przyjmujący komunikat, atrybut args i możliwość łapania w bloku except . To pokazuje, jak potężne jest dziedziczenie w Pythonie - nawet pusta klasa staje się pełnoprawnym wyjątkiem.

Klasa pusta z samym pass to najprostszy możliwy przykład ilustrujący podstawową składnię klas w Pythonie. Nawet tak minimalna definicja jest poprawną klasą, z której można tworzyć obiekty. Każda klasa w Pythonie 3 domyślnie dziedziczy po object, co zapewnia zestaw podstawowych metod specjalnych, takich jak __str__, __repr__, __eq__ czy __new__. Obiekty pustej klasy mają unikalny identyfikator w pamięci, a operator is pozwala sprawdzić ich tożsamość. Mimo że praktyczne znaczenie pustych klas jest ograniczone, stanowią one dobry punkt wyjścia do zrozumienia mechanizmów tworzenia i zarządzania obiektami.

Słowo kluczowe pass jest potrzebne, ponieważ Python wymaga, aby każdy blok kodu zawierał co najmniej jedną instrukcję. W przypadku klas, funkcji czy pętli, pass spełnia ten wymóg bez wykonywania jakiejkolwiek operacji. Jest to przydatne podczas szkicowania struktury projektu, gdy chcemy zdefiniować szkielet klasy bez implementacji jej wnętrza. Pusta klasa może być później rozszerzana o atrybuty, metody i bardziej zaawansowane mechanizmy. Wzorzec ten jest często używany w fazie projektowania, gdy najpierw definiuje się strukturę klas, a dopiero potem implementuje ich zachowania.

28 / 45 Kod: własny wyjątek z komunikatem

Domyślny komunikat w klasie

class BladWalidacji(Exception):

    def __init__(self, pole, komunikat=""):

        self.pole = pole

        self.komunikat = komunikat or f"Błąd w polu '{pole}'"

        super().__init__(self.komunikat)



def utworz_uzytkownika(nazwa, email):

    if "@" not in email:

        raise BladWalidacji("email", "Nieprawidłowy adres email.")

    if len(nazwa) < 2:

        raise BladWalidacji("nazwa")

    print("Użytkownik utworzony!")



try:

    utworz_uzytkownika("A", "test@test.pl")

except BladWalidacji as e:

    print(f"Błąd w polu '{e.pole}':", e)

Klasa BladWalidacji to przykład wyjątku z własnym konstruktorem, który przyjmuje dodatkowe parametry: nazwę pola i opcjonalny komunikat. Dzięki operatorowi or w konstruktorze, jeśli nie podamy komunikatu, zostanie wygenerowany domyślny na podstawie nazwy pola. To elegancki wzorzec, który łączy elastyczność z wygodą użycia - wywołujący może podać własny komunikat lub polegać na domyślnym.

Slajd zatytułowany "Kod: własny wyjątek z komunikatem" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

29 / 45 Kod: raise z własnym wyjątkiem

Rzucanie własnego wyjątku

class BladKonta(Exception):

    pass



class KontoBankowe:

    def __init__(self, wlasciciel, saldo=0):

        self.wlasciciel = wlasciciel

        self.saldo = saldo



    def wyplac(self, kwota):

        if kwota > self.saldo:

            raise BladKonta(f"Niewystarczające środki. Saldo: {self.saldo}, "

                             f"żądano: {kwota}")

        self.saldo -= kwota

        print(f"Wypłacono {kwota}. Nowe saldo: {self.saldo}")



konto = KontoBankowe("Anna", 100)

try:

    konto.wyplac(200)

except BladKonta as e:

    print("Błąd konta:", e)

Klasa KontoBankowe to praktyczny przykład użycia własnego wyjątku BladKonta w metodzie obiektu. Metoda wyplac sprawdza, czy żądana kwota nie przekracza salda - jeśli tak, rzuca wyjątek z komunikatem zawierającym szczegółowe informacje (aktualne saldo i żądaną kwotę). To typowy wzorzec w aplikacjach finansowych: wyjątek niesie ze sobą dane potrzebne do podjęcia decyzji, np. czy próbować przelewu z innego źródła.

Slajd zatytułowany "Kod: raise z własnym wyjątkiem" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

30 / 45 Kod: except z własnym wyjątkiem

Łapanie własnego wyjątku

class BladPilki(Exception):

    def __init__(self, nazwa_pliku, kod_bledu):

        self.nazwa_pliku = nazwa_pliku

        self.kod_bledu = kod_bledu

        super().__init__(f"Błąd pliku {nazwa_pliku} (kod: {kod_bledu})")



def otworz_plik(sciezka):

    if "." not in sciezka:

        raise BladPilki(sciezka, 1001)

    print(f"Otwieram plik: {sciezka}")



try:

    otworz_plik("dane")

except BladPilki as e:

    print("Złapano:", e)

    print("Nazwa pliku:", e.nazwa_pliku)

    print("Kod błędu:", e.kod_bledu)

Klasa BladPilki rozszerza koncepcję o kod błędu - liczbowy identyfikator problemu, który można wykorzystać do mapowania na komunikaty w różnych językach lub do kategoryzacji błędów w systemie logowania. W bloku except mamy dostęp zarówno do komunikatu (przez e ), jak i do poszczególnych atrybutów ( e.nazwa_pliku , e.kod_bledu ). Dzięki temu kod obsługujący błąd ma pełny kontekst potrzebny do podjęcia działań naprawczych.

Slajd zatytułowany "Kod: except z własnym wyjątkiem" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

31 / 45 Podsumowanie - własne klasy wyjątków

Co warto zapamiętać?

  • Własna klasa wyjątku dziedziczy po Exception
  • Może być pusta (pass) - wtedy działa jak standardowy wyjątek
  • Może rozszerzać __init__ o własne parametry i atrybuty
  • W konstruktorze wywołujemy super().__init__() z komunikatem
  • Nazwa klasy powinna kończyć się słowem Error (konwencja) lub być opisowa
  • Własne wyjątki można łapać jak każdy inny - przez except
  • Własne wyjątki ułatwiają testowanie - możesz łapać konkretny typ w asercjach testów jednostkowych
Podsumowanie

Podsumowanie to dobry moment na refleksję nad przyswojonym materiałem i identyfikację obszarów wymagających dodatkowej pracy. Wymienione punkty stanowią esencję przerobionej części kursu - od definicji klasy, przez tworzenie obiektów, aż po kompozycję i wzorzec fabryki. Każdy z tych punktów będzie rozwijany w kolejnych modułach, dlatego warto upewnić się, że są dobrze zrozumiane. Zachęcamy do tworzenia własnych notatek i map myśli, które pomagają w usystematyzowaniu wiedzy. Regularne powtórki są kluczowe dla trwałego zapamiętania materiału.

Mapy myśli są skutecznym narzędziem wizualizacji złożonych koncepcji i relacji między nimi. Przedstawiona mapa obrazuje najważniejsze pojęcia omówione w tej części kursu oraz ich wzajemne powiązania. Tworzenie własnych map myśli podczas nauki programowania aktywuje inne obszary mózgu niż czytanie liniowego tekstu, co przekłada się na lepsze zapamiętywanie. Studenci, którzy regularnie tworzą mapy myśli, osiągają lepsze wyniki w testach koncepcyjnych i szybciej łączą nowe informacje z już posiadaną wiedzą. Zachęcamy do wykorzystania tej techniki.

32 / 45 Dodawanie atrybutów do własnych wyjątków

Bogatsze wyjątki

Własne wyjątki mogą przenosić dodatkowe informacje - kod błędu, dane kontekstowe, obiekty, które spowodowały problem. To jedna z głównych zalet OOP w obsłudze błędów. Zamiast zwracać kod błędu (jak w językach proceduralnych), rzucamy obiekt z pełnym kontekstem - to znacznie bardziej elastyczne, bo obiekt może zawierać dowolne atrybuty i metody.

Dzięki atrybutom w bloku except możemy podejmować decyzje na podstawie szczegółowych informacji - na przykład przekierować różne kody błędów do różnych modułów obsługi, zapisać szczegółowy kontekst do logów lub podjąć decyzję o ponownej próbie.

Zaleta: Zamiast zwracać kod błędu (jak w językach proceduralnych), rzucamy obiekt z pełnym kontekstem.
Atrybuty wyjątków

Atrybuty są podstawowym mechanizmem przechowywania stanu obiektu i mogą zawierać dane dowolnego typu dostępnego w Pythonie. Każdy obiekt ma własną, niezależną kopię atrybutów zdefiniowanych w konstruktorze, co oznacza, że zmiana wartości w jednej instancji nie wpływa na pozostałe. W Pythonie atrybuty są przechowywane w słowniku __dict__ każdego obiektu, co umożliwia dynamiczne dodawanie i usuwanie atrybutów w czasie wykonania. Chociaż dynamiczne dodawanie atrybutów jest możliwe, w praktyce zaleca się definiowanie wszystkich atrybutów w konstruktorze __init__ dla zachowania przewidywalności kodu. Taki nawyk sprawia, że struktura obiektu jest jasna dla każdego programisty czytającego definicję klasy. Ponadto wiele narzędzi do statycznej analizy kodu wymaga jawnego deklarowania atrybutów.

Konstruktor __init__ jest wywoływany automatycznie po utworzeniu obiektu przez metodę __new__, która alokuje pamięć dla nowej instancji. Zadaniem __init__ jest przygotowanie obiektu do użycia poprzez ustawienie początkowych wartości atrybutów i wykonanie ewentualnych czynności inicjalizacyjnych. W przeciwieństwie do niektórych innych języków, Python nie wspiera przeciążania konstruktorów - zamiast tego stosuje się parametry opcjonalne z wartościami domyślnymi oraz wzorzec fabryki. Parametr self, obowiązkowy w każdej metodzie instancyjnej, jest referencją do konkretnego obiektu, na którym wywołano metodę. Dzięki self metoda ma dostęp do wszystkich atrybutów i innych metod danego obiektu.

33 / 45 Kod: wyjątek z kodem błędu

Kod błędu w wyjątku

class BladAplikacji(Exception):

    def __init__(self, komunikat, kod_bledu):

        self.kod_bledu = kod_bledu

        super().__init__(f"[{kod_bledu}] {komunikat}")



def przetworz_zamowienie(zamowienie_id):

    if zamowienie_id <= 0:

        raise BladAplikacji("Nieprawidłowe ID zamówienia.", 4001)

    print(f"Przetwarzanie zamówienia #{zamowienie_id}")



try:

    przetworz_zamowienie(0)

except BladAplikacji as e:

    print(f"Kod: {e.kod_bledu}, Treść: {e}")

    # Kod: 4001, Treść: [4001] Nieprawidłowe ID zamówienia.

Klasa BladAplikacji łączy komunikat tekstowy z kodem błędu, formatując je w konstruktorze nadrzędnym w postaci [4001] Treść . Dzięki wywołaniu super().__init__(...) komunikat jest dostępny zarówno przez rzutowanie na napis ( str(e) ), jak i przez atrybut e.kod_bledu . To standardowy wzorzec przy tworzeniu własnych wyjątków z dodatkowymi danymi.

Kod błędu

Slajd zatytułowany "Kod: wyjątek z kodem błędu" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

34 / 45 Kod: wyjątek z danymi

Przechowywanie danych w wyjątku

class BladImportuDanych(Exception):

    def __init__(self, nazwa_pliku, numer_linii, tresc_linii, powod):

        self.nazwa_pliku = nazwa_pliku

        self.numer_linii = numer_linii

        self.tresc_linii = tresc_linii

        komunikat = f"Błąd w pliku {nazwa_pliku}, linia {numer_linii}: {powod}"

        super().__init__(komunikat)



def importuj_linie(linia, numer, nazwa_pliku):

    dane = linia.strip().split(",")

    if len(dane) != 3:

        raise BladImportuDanych(nazwa_pliku, numer, linia,

                               "Oczekiwano 3 kolumn.")

    return dane



# Symulacja

try:

    importuj_linie("Anna;30\n", 5, "dane.csv")

except BladImportuDanych as e:

    print(f"Plik: {e.nazwa_pliku}, linia {e.numer_linii}")

    print(f"Treść: {e.tresc_linii.strip()}")

Klasa BladImportuDanych przechowuje rozbudowany kontekst błędu: nazwę pliku, numer linii, treść linii i przyczynę niepowodzenia. To modelowy przykład wyjątku w aplikacji do przetwarzania danych - zamiast rzucać ogólnikowy ValueError , dostarczamy wszystkich informacji potrzebnych do szybkiego zdiagnozowania i naprawienia problemu. W praktyce takie wyjątki są bezcenne podczas debugowania złożonych procesów ETL.

Wyjątek z danymi

Slajd zatytułowany "Kod: wyjątek z danymi" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

35 / 45 Podsumowanie - atrybuty wyjątków

Kluczowe wnioski

  • Atrybuty w wyjątkach pozwalają przekazać więcej informacji niż sam komunikat
  • Dzięki OOP możemy tworzyć wyjątki z dowolnymi danymi - kodami, obiektami, listami itp.
  • W bloku except mamy dostęp do wszystkich atrybutów przez as e
  • To jeden z powodów, dla których wyjątki w Pythonie są lepsze od zwracania kodów błędów
  • Atrybuty można wykorzystać do podejmowania decyzji w bloku except - np. różne działania dla różnych kodów błędu
Dobra praktyka: Projektuj wyjątki tak, by zawierały wszystkie informacje potrzebne do obsługi błędu.

Atrybuty są podstawowym mechanizmem przechowywania stanu obiektu i mogą zawierać dane dowolnego typu dostępnego w Pythonie. Każdy obiekt ma własną, niezależną kopię atrybutów zdefiniowanych w konstruktorze, co oznacza, że zmiana wartości w jednej instancji nie wpływa na pozostałe. W Pythonie atrybuty są przechowywane w słowniku __dict__ każdego obiektu, co umożliwia dynamiczne dodawanie i usuwanie atrybutów w czasie wykonania. Chociaż dynamiczne dodawanie atrybutów jest możliwe, w praktyce zaleca się definiowanie wszystkich atrybutów w konstruktorze __init__ dla zachowania przewidywalności kodu. Taki nawyk sprawia, że struktura obiektu jest jasna dla każdego programisty czytającego definicję klasy. Ponadto wiele narzędzi do statycznej analizy kodu wymaga jawnego deklarowania atrybutów.

Konstruktor __init__ jest wywoływany automatycznie po utworzeniu obiektu przez metodę __new__, która alokuje pamięć dla nowej instancji. Zadaniem __init__ jest przygotowanie obiektu do użycia poprzez ustawienie początkowych wartości atrybutów i wykonanie ewentualnych czynności inicjalizacyjnych. W przeciwieństwie do niektórych innych języków, Python nie wspiera przeciążania konstruktorów - zamiast tego stosuje się parametry opcjonalne z wartościami domyślnymi oraz wzorzec fabryki. Parametr self, obowiązkowy w każdej metodzie instancyjnej, jest referencją do konkretnego obiektu, na którym wywołano metodę. Dzięki self metoda ma dostęp do wszystkich atrybutów i innych metod danego obiektu.

36 / 45 Metody rzucające wyjątki - walidacja w metodach

Wyjątki jako mechanizm walidacji

W OOP często metody klas walidują swoje argumenty i rzucają wyjątki, gdy dane są niepoprawne. To eleganckie rozwiązanie - obiekt sam dba o swoją poprawność, a kod zewnętrzny nie musi pamiętać o ręcznym sprawdzaniu stanu po każdej operacji.

Zalety takiego podejścia:

  • Kod klienta (użytkownika klasy) wie, że coś poszło nie tak
  • Można łatwo odróżnić normalny przepływ od błędu
  • Wyjątki są częścią interfejsu klasy - dokumentują, jakie błędy mogą wystąpić
  • Dziedziczenie pozwala łapać wyjątki na różnych poziomach ogólności - od konkretnego błędu po ogólny typ nadrzędny
Metody z wyjątkami

Metody są funkcjami zdefiniowanymi w przestrzeni nazw klasy, które otrzymują automatycznie pierwszy argument w postaci referencji do obiektu. Dzięki temu mogą odczytywać i modyfikować stan obiektu, na którym zostały wywołane. W Pythonie istnieje kilka rodzajów metod: instancyjne (z self), klasowe (z cls i dekoratorem @classmethod), statyczne (z @staticmethod) oraz abstrakcyjne (z @abstractmethod w klasach ABC). Metody instancyjne są najczęściej używane i to one będą głównym tematem tej części kursu. Każda metoda instancyjna przyjmuje self jako pierwszy parametr, a Python automatycznie przekazuje obiekt w momencie wywołania przez notację kropkową. Metody mogą przyjmować dodatkowe argumenty, mieć wartości domyślne i zwracać wartości za pomocą instrukcji return.

Dobrą praktyką projektowania metod jest zasada pojedynczej odpowiedzialności - każda metoda powinna wykonywać jedną, dobrze określoną operację. Metody tylko do odczytu stanu, nazywane getterami, nie powinny modyfikować atrybutów obiektu. Metody modyfikujące stan, nazywane setterami, powinny walidować dane wejściowe przed wprowadzeniem zmian. Przestrzeganie tych zasad prowadzi do kodu łatwiejszego w testowaniu i debugowaniu. Warto również stosować metody pomocnicze, aby uniknąć powielania kodu wewnątrz klasy. Dobrze zaprojektowane metody sprawiają, że klasa jest intuicyjna w użyciu i trudna do niepoprawnego wykorzystania.

37 / 45 Kod: metoda z walidacją i raise

Walidacja w metodzie klasy

class Osoba:

    def __init__(self, imie, wiek):

        self.imie = imie

        self.wiek = wiek



    def ustaw_wiek(self, nowy_wiek):

        if not isinstance(nowy_wiek, (int, float)):

            raise TypeError("Wiek musi być liczbą.")

        if nowy_wiek < 0 or nowy_wiek > 150:

            raise ValueError(f"Wiek {nowy_wiek} jest poza zakresem 0-150.")

        self.wiek = nowy_wiek



    def przedstaw_sie(self):

        return f"Jestem {self.imie}, mam {self.wiek} lat."



os = Osoba("Tomasz", 30)

try:

    os.ustaw_wiek(-5)

except (TypeError, ValueError) as e:

    print("Błąd:", e)

Klasa Osoba demonstruje, jak metoda ustaw_wiek broni się przed niepoprawnymi danymi. Dwa osobne warunki sprawdzają typ ( isinstance ) i zakres wartości, rzucając odpowiednio TypeError lub ValueError . Dzięki temu obiekt Osoba zawsze pozostaje w spójnym stanie - wiek nigdy nie przyjmie wartości ujemnej czy nierzeczywistej. To realizacja zasady hermetyzacji: obiekt pilnuje swoich danych, a nie ufa ślepo wywołującemu.

Metoda z walidacją

Metody są funkcjami zdefiniowanymi w przestrzeni nazw klasy, które otrzymują automatycznie pierwszy argument w postaci referencji do obiektu. Dzięki temu mogą odczytywać i modyfikować stan obiektu, na którym zostały wywołane. W Pythonie istnieje kilka rodzajów metod: instancyjne (z self), klasowe (z cls i dekoratorem @classmethod), statyczne (z @staticmethod) oraz abstrakcyjne (z @abstractmethod w klasach ABC). Metody instancyjne są najczęściej używane i to one będą głównym tematem tej części kursu. Każda metoda instancyjna przyjmuje self jako pierwszy parametr, a Python automatycznie przekazuje obiekt w momencie wywołania przez notację kropkową. Metody mogą przyjmować dodatkowe argumenty, mieć wartości domyślne i zwracać wartości za pomocą instrukcji return.

Dobrą praktyką projektowania metod jest zasada pojedynczej odpowiedzialności - każda metoda powinna wykonywać jedną, dobrze określoną operację. Metody tylko do odczytu stanu, nazywane getterami, nie powinny modyfikować atrybutów obiektu. Metody modyfikujące stan, nazywane setterami, powinny walidować dane wejściowe przed wprowadzeniem zmian. Przestrzeganie tych zasad prowadzi do kodu łatwiejszego w testowaniu i debugowaniu. Warto również stosować metody pomocnicze, aby uniknąć powielania kodu wewnątrz klasy. Dobrze zaprojektowane metody sprawiają, że klasa jest intuicyjna w użyciu i trudna do niepoprawnego wykorzystania.

38 / 45 Kod: łapanie wyjątku z metody

Obsługa wyjątku z metody

class Kalkulator:

    @staticmethod

    def podziel(a, b):

        if b == 0:

            raise ZeroDivisionError("Dzielenie przez zero!")

        return a / b



    @staticmethod

    def pierwiastek(x):

        if x < 0:

            raise ValueError("Nie ma pierwiastka z liczby ujemnej.")

        return x ** 0.5



# Użycie z obsługą błędów

def wykonaj_obliczenia(a, b):

    try:

        iloraz = Kalkulator.podziel(a, b)

        print(f"Iloraz: {iloraz}")

    except ZeroDivisionError as e:

        print("Błąd:", e)



    try:

        pierwiastek = Kalkulator.pierwiastek(a)

        print(f"Pierwiastek z {a}: {pierwiastek}")

    except ValueError as e:

        print("Błąd:", e)



wykonaj_obliczenia(-9, 0)

Klasa Kalkulator używa dekoratora @staticmethod , ponieważ jej metody nie potrzebują dostępu do stanu instancji - są czystymi funkcjami matematycznymi. Każda z metod rzuca odpowiedni wyjątek, gdy dane wejściowe są niepoprawne. Funkcja wykonaj_obliczenia pokazuje, jak łapać te wyjątki na poziomie wywołania, dzięki czemu klasa Kalkulator pozostaje czysta i nie zajmuje się obsługą błędów - to odpowiedzialność kodu klienckiego.

Lapanie z metody

Metody są funkcjami zdefiniowanymi w przestrzeni nazw klasy, które otrzymują automatycznie pierwszy argument w postaci referencji do obiektu. Dzięki temu mogą odczytywać i modyfikować stan obiektu, na którym zostały wywołane. W Pythonie istnieje kilka rodzajów metod: instancyjne (z self), klasowe (z cls i dekoratorem @classmethod), statyczne (z @staticmethod) oraz abstrakcyjne (z @abstractmethod w klasach ABC). Metody instancyjne są najczęściej używane i to one będą głównym tematem tej części kursu. Każda metoda instancyjna przyjmuje self jako pierwszy parametr, a Python automatycznie przekazuje obiekt w momencie wywołania przez notację kropkową. Metody mogą przyjmować dodatkowe argumenty, mieć wartości domyślne i zwracać wartości za pomocą instrukcji return.

Dobrą praktyką projektowania metod jest zasada pojedynczej odpowiedzialności - każda metoda powinna wykonywać jedną, dobrze określoną operację. Metody tylko do odczytu stanu, nazywane getterami, nie powinny modyfikować atrybutów obiektu. Metody modyfikujące stan, nazywane setterami, powinny walidować dane wejściowe przed wprowadzeniem zmian. Przestrzeganie tych zasad prowadzi do kodu łatwiejszego w testowaniu i debugowaniu. Warto również stosować metody pomocnicze, aby uniknąć powielania kodu wewnątrz klasy. Dobrze zaprojektowane metody sprawiają, że klasa jest intuicyjna w użyciu i trudna do niepoprawnego wykorzystania.

39 / 45 Podsumowanie - metody rzucające wyjątki

Co warto zapamiętać?

  • Metoda może rzucać wyjątek - to sygnał dla wywołującego, że coś poszło nie tak
  • Walidacja w metodzie to dobra praktyka - obiekt pilnuje swoich danych
  • Wywołanie metody może być otoczone try, by łapać błędy
  • Dokumentuj wyjątki, jakie może rzucić metoda - pomaga to użytkownikom klasy
  • Statyczne metody (@staticmethod) również mogą rzucać wyjątki
  • Unikaj łapania wyjątku zaraz po rzuceniu w tej samej metodzie - pozwól mu propagować do miejsca, gdzie ma sens obsługa
Podsumowanie metod

Metody są funkcjami zdefiniowanymi w przestrzeni nazw klasy, które otrzymują automatycznie pierwszy argument w postaci referencji do obiektu. Dzięki temu mogą odczytywać i modyfikować stan obiektu, na którym zostały wywołane. W Pythonie istnieje kilka rodzajów metod: instancyjne (z self), klasowe (z cls i dekoratorem @classmethod), statyczne (z @staticmethod) oraz abstrakcyjne (z @abstractmethod w klasach ABC). Metody instancyjne są najczęściej używane i to one będą głównym tematem tej części kursu. Każda metoda instancyjna przyjmuje self jako pierwszy parametr, a Python automatycznie przekazuje obiekt w momencie wywołania przez notację kropkową. Metody mogą przyjmować dodatkowe argumenty, mieć wartości domyślne i zwracać wartości za pomocą instrukcji return.

Dobrą praktyką projektowania metod jest zasada pojedynczej odpowiedzialności - każda metoda powinna wykonywać jedną, dobrze określoną operację. Metody tylko do odczytu stanu, nazywane getterami, nie powinny modyfikować atrybutów obiektu. Metody modyfikujące stan, nazywane setterami, powinny walidować dane wejściowe przed wprowadzeniem zmian. Przestrzeganie tych zasad prowadzi do kodu łatwiejszego w testowaniu i debugowaniu. Warto również stosować metody pomocnicze, aby uniknąć powielania kodu wewnątrz klasy. Dobrze zaprojektowane metody sprawiają, że klasa jest intuicyjna w użyciu i trudna do niepoprawnego wykorzystania.

40 / 45 Kontekst wyjątku: raise ... from ...

Łańcuch wyjątków

Python pozwala łańcuchować wyjątki za pomocą składni raise ... from ... . Dzięki temu możemy zachować oryginalny kontekst błędu, jednocześnie rzucając własny wyjątek wyższego poziomu. To kluczowe w architekturze wielowarstwowej - niskopoziomowy błąd (np. błąd SQL) zostaje opakowany w wyjątek biznesowy bez utraty oryginalnej przyczyny.

try:

    # kod rzucający np. ValueError

    int("abc")

except ValueError as e:

    raise BladAplikacji("Nie udało się przetworzyć danych.") from e

W tracebacku zobaczymy: "The above exception was the direct cause of the following exception". Dzięki raise ... from atrybut __cause__ nowego wyjątku przechowuje referencję do oryginalnego błędu. W złożonych systemach to często jedyny sposób, by zrozumieć, co naprawdę poszło nie tak - górny wyjątek mówi "co", a dolny, zapisany w __cause__ , mówi "dlaczego".

raise from

Slajd zatytułowany "Kontekst wyjątku: raise ... from ..." przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

41 / 45 Kod: raise ... from ...

Przykład łańcucha wyjątków

class BladPrzetwarzania(Exception):

    pass



def wczytaj_i_konwertuj(sciezka):

    try:

        with open(sciezka, "r") as f:

            dane = f.read()

        liczba = int(dane.strip())

        return liczba

    except FileNotFoundError as e:

        raise BladPrzetwarzania(f"Nie znaleziono pliku: {sciezka}") from e

    except ValueError as e:

        raise BladPrzetwarzania(f"Nieprawidłowe dane w pliku: {sciezka}") from e



try:

    wczytaj_i_konwertuj("nieistniejacy.txt")

except BladPrzetwarzania as e:

    print("Błąd przetwarzania:", e)

    print("Przyczyna:", e.__cause__)

Funkcja wczytaj_i_konwertuj to typowy przykład warstwy dostępu do danych, która opakowuje niskopoziomowe wyjątki ( FileNotFoundError , ValueError ) we własny wyjątek biznesowy BladPrzetwarzania . Dzięki składni raise ... from e oryginalna przyczyna jest zachowana w e.__cause__ i dostępna do wglądu. To kluczowy wzorzec w architekturze warstwowej: każda warstwa rzuca własne wyjątki, ale nie tracimy informacji o tym, co wydarzyło się niżej.

Przykład raise from

Slajd zatytułowany "Kod: raise ... from ..." przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

42 / 45 Kod: bez from vs z from

Porównanie

class BladBiznesowy(Exception):

    pass



# Bez 'from' – traceback nie pokazuje oryginalnego kontekstu

def bez_from():

    try:

        return 1 / 0

    except ZeroDivisionError:

        raise BladBiznesowy("Coś poszło nie tak!")



# Z 'from' – traceback łączy wyjątki

def z_from():

    try:

        return 1 / 0

    except ZeroDivisionError as e:

        raise BladBiznesowy("Coś poszło nie tak!") from e



# Test:

# bez_from()  – pokaże tylko BladBiznesowy

# z_from()    – pokaże BladBiznesowy ORAZ ZeroDivisionError jako przyczynę

Różnica między tymi dwiema funkcjami jest subtelna w kodzie, ale dramatyczna w tracebacku. bez_from traci oryginalny kontekst - widzimy tylko BladBiznesowy . z_from zachowuje pełny łańcuch: ZeroDivisionError jako przyczynę BladBiznesowy . W praktyce produkcyjnej różnica ta może zaoszczędzić godzin debugowania - widząc tylko "Coś poszło nie tak!" bez kontekstu, nie wiemy, od czego zacząć szukanie.

Porównanie from

Slajd zatytułowany "Kod: bez from vs z from" przedstawia istotne zagadnienie z zakresu programowania obiektowego w Pythonie. Zrozumienie przedstawionych tu koncepcji jest niezbędne do dalszej nauki i praktycznego stosowania OOP w codziennej pracy programisty. Zaleca się dokładne przeanalizowanie przykładów kodu i samodzielne ich przetestowanie w środowisku REPL lub edytorze. Warto również zwrócić uwagę na powiązania między tym tematem a innymi zagadnieniami omawianymi w kursie. Systematyczne budowanie wiedzy krok po kroku to klucz do opanowania programowania obiektowego w Pythonie. Nie pomijaj żadnego slajdu, nawet jeśli wydaje Ci się, że temat jest Ci już znany - powtórka utrwala wiedzę i pozwala dostrzec nowe szczegóły w znajomym materiale.

Zachęcamy do samodzielnego eksperymentowania z omawianymi mechanizmami i modyfikowania przykładowego kodu. Praktyczne ćwiczenia i własne projekty to najskuteczniejsza metoda nauki programowania, ponieważ wymagają aktywnego stosowania wiedzy. Pamiętaj, że błędy są naturalną częścią procesu uczenia się i każda pomyłka przybliża Cię do mistrzostwa. Warto prowadzić własny dziennik błędów, w którym zapisujesz napotkane problemy i ich rozwiązania. Taki zeszyt stanie się z czasem bezcennym źródłem wiedzy i punktem odniesienia na przyszłość. Korzystaj z dokumentacji oficjalnej Pythona oraz społeczności programistycznych - to nieocenione źródła wiedzy i wsparcia w trudnych momentach.

43 / 45 Praktyczny przykład: Bankomat z BladBankomatu

Klasa BladBankomatu i Bankomat

class BladBankomatu(Exception):

    def __init__(self, kod, komunikat):

        self.kod = kod

        super().__init__(f"[{kod}] {komunikat}")



class BladBrakuSrodkow(BladBankomatu):

    def __init__(self, saldo, kwota):

        super().__init__(1001, f"Niewystarczające środki. "

                         f"Saldo: {saldo}, żądano: {kwota}")



class BladNiepoprawnejKwoty(BladBankomatu):

    def __init__(self, kwota):

        super().__init__(1002, f"Niepoprawna kwota: {kwota}. "

                         f"Kwota musi być dodatnia.")



class Bankomat:

    def __init__(self, stan_srodkow=10000):

        self.stan_srodkow = stan_srodkow



    def wyplac(self, kwota):

        if not isinstance(kwota, (int, float)) or kwota <= 0:

            raise BladNiepoprawnejKwoty(kwota)

        if kwota > self.stan_srodkow:

            raise BladBrakuSrodkow(self.stan_srodkow, kwota)

        self.stan_srodkow -= kwota

        print(f"Wypłacono {kwota} zł. Pozostało: {self.stan_srodkow} zł.")

To jest rozbudowany, realistyczny przykład hierarchii własnych wyjątków. BladBankomatu jest klasą bazową, a BladBrakuSrodkow i BladNiepoprawnejKwoty dziedziczą po niej, dziedzicząc automatycznie kod błędu i mechanizm formatowania komunikatu. Dzięki temu w bloku except BladBankomatu łapiemy wszystkie błędy bankomatu, ale w razie potrzeby możemy łapać konkretny podtyp. Klasa Bankomat używa tych wyjątków w metodzie wyplac , walidując typ kwoty, jej wartość i dostępne środki.

Bankomat

Błędy są naturalną i nieodłączną częścią procesu uczenia się programowania. Każdy, nawet najbardziej doświadczony programista, popełnia błędy na co dzień - kluczowa jest umiejętność ich szybkiego identyfikowania i poprawiania. Przedstawione na tym slajdzie typowe pomyłki zostały zebrane na podstawie wieloletnich doświadczeń nauczycieli programowania i występują u większości początkujących. Zapamiętanie ich i zrozumienie przyczyn pomoże Ci uniknąć frustracji i straconego czasu na debugowanie. Warto również zapoznać się z technikami debugowania, takimi jak użycie print(), logging czy debuggera wbudowanego w IDE. Świadomość typowych pułapek to pierwszy krok do ich unikania.

Nowoczesne edytory kodu i IDE oferują wiele narzędzi pomagających w wykrywaniu błędów jeszcze przed uruchomieniem programu. PyCharm, VS Code z wtyczką Python, a nawet zaawansowane edytory tekstu z obsługą lintingu potrafią ostrzegać przed wieloma typowymi pomyłkami w czasie rzeczywistym. Korzystanie z type hintów, narzędzi takich jak mypy do statycznej analizy typów oraz systemów CI/CD z automatycznym uruchamianiem testów znacząco redukuje liczbę błędów w kodzie produkcyjnym. Warto od początku nauki wyrobić sobie nawyk korzystania z tych narzędzi, ponieważ znacząco podnoszą one jakość i niezawodność tworzonego oprogramowania.

44 / 45 Kod: testowanie Bankomatu

Testowanie hierarchii wyjątków Bankomatu

# Testowanie Bankomatu

bankomat = Bankomat(5000)



# Test 1: wypłata OK

try:

    bankomat.wyplac(1000)

except BladBankomatu as e:

    print(e)



# Test 2: za duża kwota

try:

    bankomat.wyplac(10000)

except BladBankomatu as e:

    print(f"Kod {e.kod}: {e}")



# Test 3: niepoprawna kwota

try:

    bankomat.wyplac(-50)

except BladBankomatu as e:

    print(f"Kod {e.kod}: {e}")



# Test 4: łapanie konkretnego typu

try:

    bankomat.wyplac("sto")

except BladNiepoprawnejKwoty as e:

    print("Konkretny błąd kwoty:", e)

Dzięki hierarchii wyjątków możemy łapać ogólny BladBankomatu lub konkretne typy BladNiepoprawnejKwoty , BladBrakuSrodkow . Testowanie pokazuje wszystkie scenariusze: udaną wypłatę, brak środków, niepoprawną kwotę (ujemną) oraz zły typ danych (napis "sto"). Każdy przypadek jest obsłużony odpowiednim blokiem except . To doskonały przykład, jak projektować hierarchie wyjątków w rzeczywistych aplikacjach.

Testowanie Bankomatu

Quiz podsumowujący to nie tylko sprawdzenie wiedzy, ale także okazja do utrwalenia najważniejszych koncepcji poprzez aktywne przypominanie sobie materiału. Badania z zakresu neurodydaktyki pokazują, że testowanie własnej wiedzy jest jedną z najskuteczniejszych metod uczenia się, znacznie efektywniejszą niż bierne czytanie. Każde pytanie quizu zostało starannie zaprojektowane, aby sprawdzić zrozumienie konkretnego zagadnienia, a nie tylko pamięciowe odtworzenie definicji. Jeżeli któreś pytanie sprawiło Ci trudność, potraktuj to jako sygnał, że dany temat wymaga powtórzenia. Wróć do odpowiedniego slajdu i przeanalizuj go jeszcze raz, tym razem zwracając uwagę na szczegóły, które mogły Ci umknąć.

Sukces w nauce programowania polega na systematycznym budowaniu wiedzy - każda kolejna część opiera się na fundamentach z części poprzednich. Jeżeli masz wątpliwości co do którejkolwiek koncepcji, nie przechodź dalej, dopóki jej nie wyjaśnisz. Wykorzystaj dostępne zasoby: dokumentację Pythona, fora społecznościowe, tutoriale wideo i oczywiście możliwość eksperymentowania we własnym środowisku programistycznym. Pamiętaj, że każdy zaawansowany programista zaczynał od podstaw i pokonał te same trudności co Ty teraz. Gratulujemy ukończenia kolejnego etapu nauki i życzymy powodzenia w dalszej części kursu.

45 / 45 Podsumowanie i mapa myśli

Co omówiliśmy w tej części?

  • Czym są wyjątki - mechanizm sygnalizowania błędów
  • try / except / else / finally - obsługa wyjątków
  • Hierarchia wyjątków - BaseException → Exception → konkretne typy
  • Łapanie wielu typów - krotka lub osobne bloki
  • raise - ręczne zgłaszanie wyjątków
  • Własne klasy wyjątków - dziedziczenie po Exception
  • Atrybuty wyjątków - kody błędów, dane kontekstowe
  • Metody rzucające wyjątki - walidacja w OOP
  • raise ... from ... - łańcuch wyjątków
  • LBYL vs EAFP - dwa filozoficzne podejścia do obsługi błędów w Pythonie
  • Hierarchia Bankomatu - praktyczny przykład własnych wyjątków w aplikacji biznesowej
Następna część: Wzorce projektowe w Pythonie - pierwsze kroki.
Podsumowanie

Podsumowanie to dobry moment na refleksję nad przyswojonym materiałem i identyfikację obszarów wymagających dodatkowej pracy. Wymienione punkty stanowią esencję przerobionej części kursu - od definicji klasy, przez tworzenie obiektów, aż po kompozycję i wzorzec fabryki. Każdy z tych punktów będzie rozwijany w kolejnych modułach, dlatego warto upewnić się, że są dobrze zrozumiane. Zachęcamy do tworzenia własnych notatek i map myśli, które pomagają w usystematyzowaniu wiedzy. Regularne powtórki są kluczowe dla trwałego zapamiętania materiału.

Mapy myśli są skutecznym narzędziem wizualizacji złożonych koncepcji i relacji między nimi. Przedstawiona mapa obrazuje najważniejsze pojęcia omówione w tej części kursu oraz ich wzajemne powiązania. Tworzenie własnych map myśli podczas nauki programowania aktywuje inne obszary mózgu niż czytanie liniowego tekstu, co przekłada się na lepsze zapamiętywanie. Studenci, którzy regularnie tworzą mapy myśli, osiągają lepsze wyniki w testach koncepcyjnych i szybciej łączą nowe informacje z już posiadaną wiedzą. Zachęcamy do wykorzystania tej techniki.