Sterowanie przepływem w Pythonie — instrukcje warunkowe

Sterowanie przepływem? Pętle? Instrukcje warunkowe? O co tu w ogóle chodzi?

Wyobraź sobie sytuację, że ludzie komunikują się ze sobą, nie używając w ogóle zdań podrzędnie złożonych warunkowych. Życie byłoby bardzo trudne. Nie moglibyśmy np. stworzyć zdania: “A jak Ci na mnie zależy, to do mnie napisz, bo inaczej będę… smutna, a ja tego nie chcę!” Jakby to przełożyć na kod, to mamy klasyczny “if/else”, ale w wydaniu ludzkim (och! jak ludzkim!), a nie pythonowskim.

Po co nam to?

Pętle i instrukcje warunkowe, czyli tzw. sterowanie przepływem (ang. control flow) to jedno z najważniejszych narzędzi, dzięki którym program „podejmuje decyzje” i „wykonuje coś wiele razy”. 

Bez nich skrypt byłby linearną listą komend – działającą dokładnie tak samo niezależnie od danych wejściowych i środowiska. 

Kontrola przepływu ma trzy główne zadania:

  • reaktywność na dane użytkownika (Ten sam kod potrafi odpalić różne scenariusze w zależności od sytuacji),
  • automatyzacja żmudnych czynności (Pętle zamieniają powtarzalną pracę manualną w powtarzalny algorytm, który działa szybko, bezbłędnie i o każdej porze.
  • skalowanie w czasie i wolumenie (Ta sama logika może się wykonać 1x lub 1000x za pomocą jednego fragmentu kodu.)
  • czystość kodu (Kiedy przychodzi zmiana reguły biznesowej, modyfikujesz jeden fragment kodu, a nie tysiące.)

Poniżej znajdziesz krótki tutorial, który nauczy Cię podstaw instrukcji warunkowych, a w kolejnym artykule – pętli. Polecam wkuć na blachę zasady używania i składnię, zwłaszcza jeśli w przeszłości pracowałeś_aś z innym językiem programowania. Zwłaszcza If-elsy mają w Pythonie swoje smaczki, o których warto pamiętać.

Instrukcje warunkowe (if / elif / else)

Najwyraźniej autorzy Pythona naoglądali się Gwiezdnych Wojen i lubią pisać komendy inaczej od środka (jak Yoda!) albo inaczej niż wszyscy. Co to w ogóle jest „elif”?

ElementSkładniaCo robi?Idiomy & rady
ifif warunek:Wykonuje blok, gdy warunek jest TruePython ocenia „truthiness” (puste kolekcje, 0, None zwracają False)
elifelif inny_warunek:Dodatkowe gałęzieSprawdzane dopiero, gdy poprzedni warunek był fałszywy
elseelse:Plan awaryjny, kiedy wszystko inne zawiedzieUżywaj, gdy naprawdę potrzebujesz domyślnej akcji.

Przykłady kodu:

klasyczny if-elif-else

age = 17
if age >= 18:
    print("Pełnoletni")
elif 13 <= age < 18:
    print("Nastolatek")
else:
    print("Dziecko")

operatory trójargumentowy (ang. ternary operator)

status = "pełnoletni" if age >= 18 else "niepełnoletni"

!!! Uwaga !!!
Zwróć uwagę na składnię, jest odwrotna niż w innych językach programowania.
Najpierw mamy wynik, następnie pytanie, a na końcu alternatywę.

składnia ternary operator

match-case czyli pattern matching

Począwszy od Pythona 3.10 (uwaga, jeśli kiedyś wylądujesz w projekcie z „legacy” kodem!), pojawił się pythonowski odpowiednik javowego (i typescript-owego) switcha. To czyste rozwiązanie, jeśli mamy wiele potencjalnych rozwiązań.

match zmienna:
    case "start":
        run_service()
    case "stop":
        stop_service()
    case _:
        print("Nieznana komenda")

Uwaga! Składnia case _: oznacza domyślną gałąź match-case’a. Nie jest to element obowiązkowy. Jeśli match nie znajdzie pasującej opcji, po prostu przejdzie dalej.

Typowe pułapki instrukcji warunkowych

Python ma swoje smaczki i lubi robić rzeczy po swojemu (pewnie dlatego, że wszyscy zawsze mówią, że Python jest łatwy!). Poniżej kilka drobiazgów, które często wysypują kod i człowiek później szuka godzinami błędu, a okazuje się, że zgubił jeden znak równości albo źle skopiował wcięcia.

Przypisanie zamiast porównania

Python nie pozwala na przypisanie wartości wewnątrz if-a. Dostajesz od razu SyntaxError (I bardzo dobrze, bo to bez sensu – tu patrzę z wysoko uniesioną brwią na JS-owców!).
Ale… można przypisywać wewnątrz match-case’a.

user = {"name": "Anna", "age": 30}

match user:
    case {"name": name, "age": age}:
        greeting = f"Cześć, {name}! Masz {age} lat."

Błędne wcięcia (IndentationError)

Problem z wcięciami to klasyk i jeden z powodów, dla których zawsze warto używać IDE (który w wielu przypadkach poprawi wcięcia za Ciebie). Gorzej jest w przypadkach, kiedy IDE nie jest w stanie określić, czy w danym miejscu powinno być wcięcie czy nie.

# ❌ IndentationErrorif x > 5:
print("Większe")     

#  Poprawne użycie pustego if-a:
if x > 5:    pass

print("Większe")       

# ✅ Poprawne wcięcieif x > 5:
    print("Większe")

Python oczekuje, że wszystko wewnątrz instrukcji warunkowej będzie wcięte 1 raz (czyli zazwyczaj o 4 spacje). Niestety wcięcia ustawia się w stylach IDE i czasem można się nieźle naciąć (albo… wciąć? ;)) Zawsze sprawdzaj wcięcia, jeśli kopiujesz kod lub jeśli pracujesz w większym zespole i nie macie wspólnego pliku ze stylami.

Porównania łańcuchowe (ang. chained comparisons)

Python pozwala na stosowanie „łańcuchowanie” porównań, wzorowane na matematyce.

✅ Po pythonowemu:
if 0 < x < 10:
    print("x jest w przedziale (0,10)")
✅ Też poprawnie, ale "po staremu":
if (0 < x) and (x < 10):
    print("x jest w przedziale (0,10)")

✅ Potrójne porównanie "po pythonowemu":
if a == b == c:
    print("Wszystkie są równe")

Podsumowanie

I to już koniec teorii związanej z instrukcjami warunkowymi. Obczaj naszego Colaba, w którym znajdziesz powyższe przykłady z wytłumaczeniem i zadania do poćwiczenia.

I pamiętaj! Masz jakieś pytania, wątpliwości, lub po prostu chcesz ponarzekać na pythonową składnię? Zostaw komentarz. A jeśli zrobiłeś_aś zadania, nie wrzucaj ich w komentarzach – niech inni też się pomęczą! 😉

Wszystko zrobione? Doskonale. Poklep się po pleckach i przejdź do następnego artykułu – tym razem o pętlach.

Podziel się swoją opinią

Jeden komentarz

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *