Commit 3cc27b00 by Patryk Czarnik

teoria wyjątków

parent 65d71f78
# Dobrą praktyką w programowaniu obiektowym jest nieodwoływanie się do pól (zmiennych / atrybtów)
# w obiektach poza tą klasą, tylko korzystanie z dedykowanych metod.
# Jeśli będziemy przestrzegać tej zasady, to klasa będzie mogła zapewnić poprawne działanie,
# będziemy mieć pewność, że spełnione są pewne niezmienniki (invariant).
# Np. możemy zapewnić, że saldo nie jest ujemne.
# Dużą rolę w tym pełnią wyjątki.
# Gdy jakaś operacja "widzi", że prowadziłaby do złego stanu, wyrzuca wyjątek.
# Gdy operacja jest przerywana wyjątkiem, to nie powinna ona zmieniać stanu.
class BrakSrodkow(Exception):
def __init__(self, numer, kwota, saldo):
super().__init__(f'Brak środków na koncie nr {numer}. Próbowano wypłacić {kwota}, a na koncie jest {saldo}')
self.numer = numer
self.kwota = kwota
self.saldo = saldo
class Konto:
def __init__(self, numer, wlasciciel, saldo=0):
if saldo < 0:
raise ValueError('ujemne saldo')
self._numer = numer
self._wlasciciel = wlasciciel
self._saldo = saldo
def __str__(self):
return f'Konto nr {self._numer}, saldo = {self._saldo}, wł. {self._wlasciciel}'
def wplata(self, kwota):
if kwota <= 0:
raise ValueError('niedodatnia kwota we wplata')
self._saldo += kwota
def wyplata(self, kwota):
if kwota <= 0:
raise ValueError('niedodatnia kwota w wyplata')
if kwota > self._saldo:
raise BrakSrodkow(self._numer, kwota, self._saldo)
self._saldo -= kwota
konto = Konto(1, 'Ala', 1000)
print(konto)
konto.wplata(200)
print(konto)
konto.wyplata(800)
print(konto)
try:
konto.wplata(-50)
except Exception as e:
print(e)
try:
konto.wyplata(500)
except Exception as e:
print(e)
# W tym programie nie wyłapujemy wyjątków.
# Jeśli zdarzy się wyjątek (zły format liczby, dzielenie przez zero, albo przerwanie programu Ctrl+C),
# to program kończy się natychmiast, a na "standardowe wyjście błędów" wypisuje się opis wyjątku, w tym tzw. stack trace (w Pythonie "traceback")
print('Dzień dobry')
x = int(input('Podaj pierwszą liczbę: '))
y = int(input('Podaj drugą liczbę: '))
iloraz = x / y
print('Wynik dzielenia:', iloraz)
print('Koniec programu')
# W tym programie nie wyłapujemy wyjątków.
# Jeśli zdarzy się wyjątek (zły format liczby, dzielenie przez zero, albo przerwanie programu Ctrl+C),
# to program kończy się natychmiast, a na "standardowe wyjście błędów" wypisuje się opis wyjątku, w tym tzw. stack trace (w Pythonie "traceback")
# Tutaj więcej funkcji, aby zobaczyć czym jest Traceback
def procedura1():
procedura2()
def procedura2():
procedura3()
def procedura3():
x = int(input('Podaj pierwszą liczbę: '))
y = int(input('Podaj drugą liczbę: '))
iloraz = podziel(x, y)
print('Wynik dzielenia:', iloraz)
sprawdz(iloraz)
print('OK')
def podziel(x,y):
return x / y
def sprawdz(liczba):
if liczba == 13:
raise ValueError('pechowa trzynastka')
print('Dzień dobry')
procedura1()
print('Koniec programu')
print('Dzień dobry')
try:
x = int(input('Podaj pierwszą liczbę: '))
y = int(input('Podaj drugą liczbę: '))
iloraz = x / y
print('Wynik dzielenia:', iloraz)
if iloraz == 13:
raise ValueError('pechowa trzynastka')
print('Generalnie jest OK')
except:
print('Wystąpił jakiś błąd')
# Tak napisane except wyłapuje wszystkie błędy, tak jakby działało except BaseException
print('Koniec programu')
# Uwaga, wyłapywanie WSZYSTKICH wyjątków jest ryzykowne,
# bo wówczas nie da się przerwać programu za pomocą Ctrl+C (jeśli tak jak poniższy działa w pętli)
print('Dzień dobry')
while True:
try:
x = int(input('Podaj pierwszą liczbę: '))
y = int(input('Podaj drugą liczbę: '))
iloraz = x / y
print('Wynik dzielenia:', iloraz)
except:
print('Wystąpił jakiś błąd')
print('ciąg dalszy...')
print('Koniec programu')
print('Dzień dobry')
try:
x = int(input('Podaj pierwszą liczbę: '))
y = int(input('Podaj drugą liczbę: '))
iloraz = x / y
print('Wynik dzielenia:', iloraz)
if iloraz == 13:
raise ValueError('pechowa trzynastka')
print('Generalnie jest OK')
except Exception as e:
print(f'Wystąpił błąd typu {type(e)} : {e}')
print('Koniec programu')
print('Dzień dobry')
while True:
try:
x = int(input('Podaj pierwszą liczbę: '))
y = int(input('Podaj drugą liczbę: '))
iloraz = x / y
print('Wynik dzielenia:', iloraz)
if iloraz == 13:
raise ValueError('pechowa trzynastka')
print('Generalnie jest OK')
# ten except nie wyłapie wyjątku KeyboardInterrupt, więc nciśnięcie Ctrl+C skutecznie przerwie program
except Exception as e:
print(f'Wystąpił błąd typu {type(e)} : {e}')
print('Koniec programu')
print('Dzień dobry')
try:
while True:
try:
x = int(input('Podaj pierwszą liczbę: '))
y = int(input('Podaj drugą liczbę: '))
iloraz = x / y
print('Wynik dzielenia:', iloraz)
if iloraz == 13:
raise ValueError('pechowa trzynastka')
print('Generalnie jest OK')
# ten except nie wyłapie wyjątku KeyboardInterrupt, więc nciśnięcie Ctrl+C skutecznie przerwie program
except Exception as e:
print(f'Wystąpił błąd typu {type(e)} : {e}')
except KeyboardInterrupt:
print('\nKończymy? OK...')
print('Koniec programu')
print('Dzień dobry')
try:
x = int(input('Podaj pierwszą liczbę: '))
y = int(input('Podaj drugą liczbę: '))
iloraz = x / y
print('Wynik dzielenia:', iloraz)
except ZeroDivisionError as e:
print(f'Dzielenie przez zero')
finally:
print('Finally zawsze się wykona')
# finally wykona się w każdej sytuacji:
# 1) fragment programu w try bez błędów dojdzie do końca
# 2) nastąpi wyjątek obsłużony w except
# 3) nastapi wyjątek, który nie zostanie obsłużony przez te except(y)
# 4) gdy wyjdziemy w tego fragmentu kodu w inny sposób: return, break
print('Koniec programu')
# własna klasa wyjątku - dziedziczymy z Exception i zazwyczaj niczego nie zmieniamy
class PechowaLiczba(Exception):
pass
print('Dzień dobry')
try:
x = int(input('Podaj pierwszą liczbę: '))
y = int(input('Podaj drugą liczbę: '))
iloraz = x / y
print('Wynik dzielenia:', iloraz)
if iloraz == 13.0:
raise PechowaLiczba('Wybrałeś pechową trzynastkę')
print('Wszystko było OK')
except ZeroDivisionError:
print(f'Dzielenie przez zero!')
except ValueError as e:
print(f'Wystąpił ValueError {e}')
except PechowaLiczba as e:
print('A to pech...', e)
except Exception as e:
print(f'Wystąpił inny błąd typu {type(e)} : {e}')
print('Koniec programu')
# własna klasa wyjątku - dziedziczymy z Exception i zazwyczaj niczego nie zmieniamy
class PechowaLiczba(Exception):
pass
def procedura1():
try:
x = int(input('Podaj pierwszą liczbę: '))
y = int(input('Podaj drugą liczbę: '))
if x == 33 or y == 33:
print('Przerywam procedura1, bo 33')
return
print('Wchodzę do procedura2')
procedura2(x, y)
print('procedura2 zakończona')
except ZeroDivisionError:
print(f'Dzielenie przez zero!')
except ValueError as e:
print(f'Wystąpił ValueError {e}')
except PechowaLiczba:
print('A to pech...')
except Exception as e:
print(f'Wystąpił inny błąd typu {type(e)} : {e}')
finally:
print('To się zawsze wykona')
# finally wykona się jeśli
# 1) nie było wyjątku,
# 2) był wyjątek i został wyłapany,
# 3) był wyjątek i nie został wyłapany
# 4) kiedy z tego fragmentu programu wychodzimy za pomocą return, break itp. (ale nie exit !!!)
def procedura2(x, y):
iloraz = x / y
print('Wynik dzielenia:', iloraz)
if x == 13 or y == 13:
raise PechowaLiczba('Wybrałeś pechową trzynastkę')
print('Wszystko było OK')
print('początek programu')
procedura1()
print('Koniec programu')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment