Decyzje
🎯 Po co Ci to?
Program bez decyzji jest jak droga bez skrzyżowań — zawsze ta sama trasa. Tymczasem bankomat sprawdza saldo, gra sprawdza kolizję, a formularz sprawdza, czy hasło się zgadza. W dziale 1 rysowałeś romby na schematach blokowych; dziś nauczysz się je pisać. Na deser zaprogramujesz w końcu rok przestępny — specyfikację i algorytm masz gotowe od dwóch działów.
✅ Czego się nauczysz
Po tej jednostce potrafisz:
- budować wyrażenia logiczne z porównań oraz spójników
and,or,not; - pisać rozgałęzienia
if/elif/elsei przewidywać, którą gałęzią pójdzie program; - tłumaczyć warunki z języka polskiego na Pythona — i wyłapywać, gdzie polszczyzna oszukuje.
🔁 Przypomnij sobie
Romb w schemacie blokowym (1.3) ma dwa wyjścia: TAK i NIE. if to dokładnie ten romb, a wcięcia w kodzie to jego gałęzie.
📘 Wyjaśnienie
Warunki. Porównania znasz z matematyki, w Pythonie piszą się niemal tak samo: <, >, <=, >=, != (różne). Jedna zmiana jest zdradliwa: pytanie o równość to ==, bo pojedyncze = zabrało już przypisanie. Wynikiem porównania jest wartość logiczna: True albo False — dwie jedyne wartości typu, który znasz z działu o bitach.
Warunki łączy się spójnikami: and (oba muszą zachodzić), or (wystarczy jeden), not (odwróć). Nawiasy porządkują, jak w matematyce.
wiek = 16
ma_zgode = True
moze_jechac = wiek >= 18 or (wiek >= 16 and ma_zgode)
print(moze_jechac) # True
Rozgałęzienia. Instrukcja if wykonuje wcięty blok tylko, gdy warunek jest prawdziwy; else łapie całą resztę; elif (skrót od „else if") pozwala ustawić kilka rombów w kaskadę:
punkty = int(input("Punkty: "))
if punkty >= 90:
print("celujący")
elif punkty >= 75:
print("bardzo dobry")
elif punkty >= 50:
print("dostateczny")
else:
print("do poprawy")
Program sprawdza warunki od góry i wykonuje pierwszy pasujący blok — po czym opuszcza całą kaskadę. Dlatego dla 95 punktów wypisze tylko „celujący", choć $95 \ge 75$ też jest prawdą. Kolejność warunków to część algorytmu: odwróć kaskadę (punkty >= 50 na górze), a każdy zdający dostanie „dostateczny".
🧮 Prześledź
Prześledź kaskadę ocen dla wejść: 90, 74, 50, 49. Zapisz, które warunki zostały sprawdzone (nie tylko który zadziałał).
Sprawdź odpowiedź
90: sprawdzony 1 warunek (>=90 prawda) → „celujący". 74: >=90 fałsz, >=75 fałsz, >=50 prawda → „dostateczny", sprawdzone 3. 50: identycznie 3 sprawdzenia → „dostateczny" (brzeg! równość wchodzi dzięki >=). 49: trzy fałsze → else → „do poprawy". Zauważ: else nie ma warunku — jest gwarancją, że każde dane gdzieś trafią, czyli programową wersją reguły „każda droga schematu prowadzi do Stopu".
💻 Kod krok po kroku
Rok przestępny — algorytm z jednostki 1.2 słowo w słowo przełożony na Pythona:
r = int(input("Rok: "))
if r % 400 == 0: # % to reszta z dzielenia (mod z pseudokodu)
print("przestępny")
elif r % 100 == 0: # dzieli się przez 100 (a przez 400 już nie)
print("nieprzestępny")
elif r % 4 == 0: # dzieli się przez 4 (a przez 100 już nie)
print("przestępny")
else:
print("nieprzestępny")
Przyjrzyj się kolejności: pytamy najpierw o wyjątek od wyjątku (400), potem o wyjątek (100), na końcu o regułę (4). Spróbuj w głowie odwrócić kolejność i prześledzić rok 2000 — zobaczysz, czemu kaskada od reguły do wyjątku by skłamała. Kolejność pytań to nie kosmetyka, to logika.
🐞 Znajdź błąd
Program ma wpuszczać na film osoby w wieku 13–17 lat tylko z opiekunem, a od 18 — zawsze:
wiek = int(input("Wiek: "))
opiekun = input("Jest opiekun? (t/n): ") == "t"
if wiek >= 13 and opiekun or wiek >= 18:
print("Wchodzisz")
else:
print("Niestety nie")
Dla jakich danych program zachowa się źle? (Podpowiedź: sprawdź dwunastolatka z opiekunem i… trzydziestolatka bez opiekuna — a potem dziesięciolatka z opiekunem.)
Sprawdź odpowiedź
Trzydziestolatek bez opiekuna wchodzi (dobrze — wiek >= 18 ratuje sprawę). Ale dziesięciolatek z opiekunem też wejdzie? Sprawdźmy: wiek >= 13 fałsz, więc and daje fałsz; or wiek >= 18 fałsz — nie wejdzie. Dobrze. To gdzie błąd? W wieku 13–17 bez opiekuna: wiek >= 13 prawda, opiekun fałsz → fałsz, wiek >= 18 fałsz → „Niestety nie" — poprawnie… Program jest w istocie poprawny logicznie, ale kruchy: działa tylko dzięki temu, że and wiąże mocniej niż or. Wystarczy, że ktoś „poprawi" go do wiek >= 13 and (opiekun or wiek >= 18) — i osiemnastolatek bez opiekuna nadal wejdzie, ale dwunastolatek z opiekunem już... też nie wejdzie (poprawnie), za to każdy 13+ bez opiekuna odpadnie — zmiana znaczenia! Morał podwójny: (1) ucz się, że and ma pierwszeństwo przed or, (2) i tak stawiaj nawiasy — (wiek >= 13 and opiekun) or wiek >= 18 znaczy to samo, a nie wymaga od czytelnika pamiętania reguł pierwszeństwa. Kod czyta się częściej, niż pisze.
⚠️ Uwaga, pułapka
Polskie „lub" bywa podstępne. „Wstęp wolny dla uczniów i studentów" znaczy: jesteś uczniem lub studentem (uczen or student) — a nie and (jedną osobą będącą uczniem i studentem naraz). Przy tłumaczeniu warunków z polskiego zawsze pytaj: „czy oba naraz, czy wystarczy jedno?" — język naturalny i logika częściej się tu rozjeżdżają, niż zgadzają.
🛠️ Teraz Ty
Napisz kalkulator BMI z klasyfikacją: pyta o masę i wzrost, liczy $\text{BMI} = \frac{\text{masa}}{\text{wzrost}^2}$ (wzrost w metrach; potęga to ** — wzrost ** 2), po czym kaskadą if/elif/else wypisuje kategorię (np. do 18,5 / do 25 / do 30 / powyżej). Przetestuj na wartościach brzegowych kategorii — dokładnie 25.0 powinno trafić tam, gdzie zaplanowałeś, a nie „gdzieś".
📐 Definicje tej lekcji
- Wyrażenie logiczne — konstrukcja o wartości
True/False, zbudowana z porównań i spójnikówand/or/not. if/elif/else— rozgałęzienie: pierwszy prawdziwy warunek wygrywa,elsełapie resztę.%(reszta z dzielenia) — pythonowy zapismod;r % 4 == 0czyta się „r dzieli się przez 4".
📌 Najważniejsze w pigułce
==pyta,=przypisuje — pomylenie ich to błąd składni, na szczęście głośny.- Kaskada
if/elif/elsewykonuje pierwszy pasujący blok; kolejność warunków to logika, nie estetyka. andwiąże mocniej niżor; nawiasy stawiaj dla ludzi, nie dla interpretera.
🎒 Zadania
- Bez komputera: jaką wartość mają wyrażenia dla
a = 4,b = 10? (a)a < 5 and b < 5, (b)a < 5 or b < 5, (c)not (a == b), (d)a * 2 <= b <= a * 3.
Wskazówka i odpowiedź
(a) True and False → False. (b) True or False → True. (c) not False → True. (d) Python pozwala łańcuchować porównania jak w matematyce: $8 \le 10 \le 12$ → True. Ten łańcuchowy zapis to rzadkość wśród języków — doceniaj go, ale wiedz, że w wielu innych językach trzeba pisać a*2 <= b and b <= a*3.
- Napisz program, który dla trzech długości boków rozstrzyga, czy da się z nich zbudować trójkąt (każdy bok krótszy od sumy dwóch pozostałych). Podaj dane testowe, w tym przypadek brzegowy 1, 2, 3.
Wskazówka i odpowiedź
Warunek: a + b > c and a + c > b and b + c > a. Dane 1, 2, 3: $1+2 = 3$, warunek > fałszywy → „nie" (trójkąt zdegenerowany do odcinka — dlatego w specyfikacji musi być ostra nierówność; gdybyś napisał >=, brzeg by Cię zdradził). Testy: (3,4,5) tak, (1,1,10) nie, (1,2,3) nie.
- Sklep daje rabat: 5% od 100 zł, 10% od 300 zł, 15% od 500 zł. Klient za 500 zł ma dostać 15%, nie 5%. Napisz kaskadę i wyjaśnij, dlaczego warunki muszą iść od największego progu.
Wskazówka i odpowiedź
if kwota >= 500:
rabat = 15
elif kwota >= 300:
rabat = 10
elif kwota >= 100:
rabat = 5
else:
rabat = 0
Gdyby progi szły od najmniejszego, klient za 500 zł spełniłby już pierwszy warunek (>= 100) i kaskada skończyłaby się na 5%. Pierwszy pasujący wygrywa — więc najbardziej wymagające warunki stawiamy na górze. Porównaj z rokiem przestępnym: to ta sama zasada.
🔍 Sprawdź, czy umiesz
- Przetłumaczyć na Pythona: „pełnoletni albo małoletni z pisemną zgodą".
- Prześledzić kaskadę
if/elif/elsedla danych brzegowych. - Wyjaśnić, czemu
=w warunku to błąd, a==w przypisaniu nie ma sensu.