Blog JSystems - uwalniamy wiedzę!

Szukaj
Animacja if/elif/else - jak Python wybiera drogę
Instrukcja if / elif / else - Python sprawdza warunki po kolei i wykonuje pierwszy prawdziwy

Czasem chcemy coś wykonać w zależności od wystąpienia lub nie jakiegoś warunku. Do takich operacji służą instrukcje warunkowe. W Pythonie mają one taką postać:

if ( jakiś warunek ):

co się ma stać gdy warunek zaistnieje

elif( jakiś warunek ):

co się ma stać gdy warunek zaistnieje

else:

co się ma stać gdy żaden z powyższych warunków nie zaistnieje

Jeden warunek

Mając w pamięci powyższą strukturę, przeanalizujmy działanie poniższego przykładu. Zaczniemy od najprostszej postaci takiej instrukcji warunkowej:

wzrost=190
if(wzrost>180):
    print('kobiety lubią to ;)')
print('no i koniec...')

Na początek deklaruję zmienną wzrost o wartości 190. If sprawdza czy wartość tej zmiennej jest większa od 180, a jeśli tak to na konsoli wyświetlany jest stosowny komunikat. Jeśli jednak warunek nie jest prawdziwy, komunikat 'kobiety lubią to' nie jest wyświetlany. Wynika to z faktu że instrukcja odpowiedzialna za wyświetlenie tego komunikatu jest powiązana z warunkiem if.

Kolejna instrukcja print już nie jest związana z wystąpieniem albo nie warunku. Dlaczego? Można to rozpoznać po odstępach instrukcji od lewej krawędzi. Elementy związane z instrukcjami warunkowymi, pętlami, należące do deklarowanej funkcji, to te które są odsunięte w prawo. W chwili gdy parser trafia na instrukcję która nie jest odsunięta w ten sposób, wie że dana instrukcja nie jest już związana z warunkiem, pętlą czy funkcją. Tak więc komunikat 'kobiety lubią to' jest związany ze spełnieniem warunku (wzrost>180), ale komunikat 'no i koniec...' już nie. Pierwszy z komunikatów zostanie wyświetlony tylko jeśli warunek zostanie spełniony, drugi bezwarunkowo. Odstępy robimy (też w zależności od środowiska IDE) spacjami lub tabulatorami. Taka składnia może się wydać nieco abstrakcyjna dla osób które przemigrowały na Pythona z innych języków programowania m.in Javy (czyli na przykład ja), ale na dłuższą metę okazuje się naprawdę bardzo wygodna.

Else

Else pozwala na określenie co ma się stać gdy warunek okaże się nieprawdziwy:

wzrost=176
if(wzrost>180):
    print('kobiety lubią to ;)')
else:
    print('smutna żaba :( ')
print('no i koniec...')

Zmieniłem wartość zmiennej "wzrost" w taki sposób by warunek w "if" nie był prawdziwy. Pierwszy komunikat jako związany ze spełnieniem warunku, nie zostaje wyświetlony. Wobec nie spełnienia warunku, wykonywane jest to co związane jest z "else". Na konsoli zostaje wyświetlony komunikat ze smutną żabą.

Wiele warunków

Możemy zechcieć sprawdzić kilka warunków. W zależności od tego czy chcemy sprawdzić je niezależnie od siebie, czy w zależności od zaistnienia lub nie innych warunków, stosujemy albo osobne bloki "if", albo w ramach jednego bloku "if" stosujemy wiele klauzul "elif". Klauzula elif pozwala sprawdzać kolejne warunki, jeśli poprzednie warunki nie były spełnione. Czyli jeśli warunek w "if" nie jest spełniony, to tylko wtedy sprawdzany jest pierwszy elif. Jeśli warunek w pierwszym elif nie jest spełniony, sprawdzany jest następny. Dzieje się tak do czasu natrafienia na spełniony warunek, lub na klauzulę "else". W przypadku spełnienia warunku, kolejne klauzule "elif" w ogóle nie są sprawdzane. Kolejne warunki są więc weryfikowane tylko jeśli wszystkie poprzednie nie były spełnione. Stąd mogłem w poniższym przykładzie posłużyć się swoistymi zakresami.

wzrost=166
if(wzrost>180):
    print('kobiety lubią to ;)')
elif(wzrost>170):
    print('przeciętny wzrost')
elif(wzrost>160):
    print('do komandosów nie przyjmą')
elif(wzrost>150):
    print('wzrost nikczemny')
else:
    print('smutna żaba :( ')
print('no i koniec...')

Za każdym razem sprawdzam tylko czy wzrost jest większy niż określona wartość, nie sprawdzam natomiast czy jest mniejszy od dolnej wartości granicznej. Komunikat "do komandosów nie przyjmą" powinien zostać wyświetlony przy wzroście 161-170 cm, a ja sprawdzam tylko czy wzrost jest większy od 160, nie sprawdzając czy aby nie przekroczył 170. Dlaczego? Wynika to bezpośrednio z tej kaskadowości warunków. Skoro parser dotarł do warunku sprawdzającego czy wzrost jest większy niż 160, to znaczy że wszystkie poprzednie warunki nie były spełnione. Piętro wyżej sprawdziłem już czy wzrost nie jest większy niż 170, a więc dotarłszy do kolejnego warunku już wiem że wzrost na pewno jest mniejszy bądź równy 170. Pozostaje mi jedynie sprawdzić dolną granicę.

Operatory logiczne w warunkach

W warunkach możemy stosować również operatory logiczne "and" i "or". Ich działanie jest zgodne z logiką matematyczną. W przypadku and obie strony muszą być spełnione by cały warunek był spełniony. W przypadku or wystarczy tylko jedna ze stron by cały warunek był prawdziwy. Oczywiście jeśli obie strony będą spełnione to warunek także jest spełniony.

wzrost=185
zarobki=1000000
if(wzrost>180 and zarobki>10000):
    print('gwiazda Tindera ;)')

Dopasowanie do wzorca - instrukcja match/case (Python 3.10 i nowsze)

Od Pythona 3.10 mamy do dyspozycji instrukcję match/case, czyli dopasowanie do wzorca (ang. structural pattern matching). To wygodniejsza i czytelniejsza alternatywa dla długiej kaskady "if/elif/else", gdy sprawdzamy jedną wartość względem wielu przypadków. Zacznijmy od najprostszego wariantu - dopasowania po wartości:

polecenie = 'start'

match polecenie:
    case 'start':
        print('Uruchamiam silnik')
    case 'stop':
        print('Zatrzymuję silnik')
    case _:
        print('Nieznane polecenie')

Wartość zmiennej "polecenie" jest porównywana kolejno z każdym "case". Podkreślnik "_" w ostatnim przypadku to tak zwany wzorzec uniwersalny - pasuje do wszystkiego, więc działa jak "else" i łapie każdą wartość, której nie obsłużyliśmy wcześniej. Kilka wartości w jednym przypadku łączymy kreską pionową "|":

match polecenie:
    case 'start' | 'wznow':
        print('Ruszamy')
    case 'stop' | 'pauza':
        print('Wstrzymuję')
    case _:
        print('Nie wiem co zrobić')

match/case potrafi znacznie więcej niż zwykłe porównanie - umie rozpakować strukturę danych i od razu przypisać jej fragmenty do zmiennych. Poniżej dopasowujemy krotkę z punktem i wyciągamy jego współrzędne, a przy okazji pilnujemy warunku dodatkowego (tak zwana straż, po angielsku guard) po słowie "if":

punkt = (0, 5)

match punkt:
    case (0, 0):
        print('Środek układu współrzędnych')
    case (0, y):
        print(f'Na osi Y, na wysokości {y}')
    case (x, 0):
        print(f'Na osi X, w pozycji {x}')
    case (x, y) if x == y:
        print('Na przekątnej')
    case (x, y):
        print(f'Punkt ({x}, {y})')

Dla prostych przypadków "jedna wartość - jedna reakcja" nadal wygodniejsze bywa zwykłe if/elif. Ale gdy sprawdzamy kształt danych (krotki, słowniki, obiekty) albo mamy kilkanaście przypadków, match/case jest zdecydowanie czytelniejszy.

Operator morsa := - przypisanie w warunku (Python 3.8 i nowsze)

Czasem chcemy w jednym miejscu policzyć wartość, od razu zapamiętać ją w zmiennej i jeszcze użyć jej w warunku. Służy do tego operator przypisania w wyrażeniu ":=", nazywany potocznie operatorem morsa (bo przypomina oczy i kły morsa). Bez niego musielibyśmy policzyć długość dwa razy albo w osobnej linii:

haslo = input('Podaj hasło: ')

if (dlugosc := len(haslo)) < 8:
    print(f'Za krótkie hasło - ma tylko {dlugosc} znaków, a potrzeba 8')

Zapis "(dlugosc := len(haslo))" liczy długość hasła, zapisuje ją do zmiennej "dlugosc" i jednocześnie zwraca tę wartość do warunku. Dzięki temu w komunikacie możemy od razu pokazać, ile znaków ma hasło, bez ponownego wywoływania funkcji len.

Komentarze (0)

Musisz być zalogowany by móc dodać komentarz. Zaloguj się przez Google

Brak komentarzy...