Pchełki Python: zaprzeczenie pętli

https://xpil.eu/g6d

Pythona używam rzadko. Prawdę powiedziawszy nigdy jeszcze nie miałem okazji napisać linijki kodu w tym języku dla któregokolwiek z moich pracodawców. Czasem zerknę w jakiś kod źródłowy, żeby "być na bieżąco". Czasem dla hecy napiszę parę prościutkich linijek. Póki co więcej mi nie potrzeba.

Python jest zwarty, elegancki, niezwykle popularny, wymusza poprawne formatowanie kodu (wcięcia!) oraz - co najważniejsze - jest aktywnie rozwijany. Ma też oczywiście wady: jest wysokopoziomowy (a więc względnie wolny), mało popularny na platformach mobilnych (Android, IOS), jest późno typowany (typy zmienych i wyrażeń są ustalane na etapie wykonania programu, a nie kompilacji) przez to uczy początkujących programistów złych nawyków, a także ułatwia popełnianie błędów związanych z rzutowaniem typów.

Jednak lubię ten język i od czasu do czasu przeglądam sobie różne materiały on-line, z czystej ciekawości.

Niedawno trafiłem na perełkę, która wprawiła mój mózguł (nie łudzę się, że mam więcej niż jeden) w lekkie zdziwienie.

Otóż okazuje się, że operatora ELSE można w Pythonie używać nie tylko jako uzupełnienia bloku IF, ale także jako dodatku do pętli FOR.

Żeby było śmieszniej (ale nie jest), działanie tego operatora w przypadku pętli FOR jest zgoła przeciwne do tego, co podpowiada nam intuicja. O ile bowiem - i jest to prawdą nie tylko w Pythonie, ale w większości języków programowania implementujących ten paradygmat - blok IF-ELSE oznacza "Wykonaj ten kawałek kodu pod takim to a takim warunkiem, w przeciwnym razie wykonaj tamten kawałek", o tyle w Pythonie blok FOR-ELSE oznacza: "Wykonaj pętlę FOR, a potem, o ile pętla zakończyła się bez używania operatora BREAK - wykonaj również ten kawałek po ELSE".

Innymi słowy - zamieszanie.

Jednak użyteczność tej konstrukcji, chociaż jej składnia może nieco razić, jest niezaprzeczalna. Weźmy taki przykład:

from math import sqrt, ceil


def is_prime(n: int):
    if(n < 3):
        return(n == 2)

    if(n % 2 == 0):
        return(False)
    else:
        for d in range(3, ceil(sqrt(n)), 2):
            if(n % d == 0):
                break
        else:
            return(True)
    return(False)
Funkcja is_prime to naiwna implementacja algorytmu sprawdzającego pierwszość liczby. Najpierw “obsługuje” przypadki szczególne (0, 1, 2), potem parzystość, a na koniec zabiera się za sprawdzanie, czy liczba dzieli się przez którąkolwiek z liczb nieparzystych począwszy od trójki aż do pierwiastka ze sprawdzanej liczby (zaokrąglonego w górę do pełnej całości).

Przy okazji: tutaj opisałem algorytm o wiele potężniejszy.

Najbardziej interesujący jest tutaj ten kawałek:

        for d in range(3, ceil(sqrt(n)), 2):
            if(n % d == 0):
                break
        else:
            return(True)
    return(False)
Pętla for wykonuje się dopóty, dopóki nieparzysta liczba d (dzielnik) nie przekroczy pierwiastka z liczby sprawdzanej (zaokrąglonego w górę), chyba że natrafimy na podzielnik – wtedy kończymy pętlę for za pomocą break. Blok else natomiast wykona się *wyłącznie* wtedy, jeżeli zakończenie pętli for nastąpiło w sposób “naturalny” (a więc jeżeli zostały wykorzystane wszystkie dostępne wartości zmiennej d i nie natrafiono na operator break).

Gdybyśmy nie mieli do dyspozycji owego else (bądź czegoś analogicznego), wówczas musielibyśmy uciekać się do tworzenia flagi (dodatkowej zmiennej), która mówiłaby nam, czy wyjście z pętli nastąpiło w wyniku znalezienia podzielnika, czy wyczerpania wiaderka z podzielnikami.

Nudne, prawda?

https://xpil.eu/g6d

6 komentarzy

  1. Nudne, nudne, ale doczytałem do końca, oczywiście pomijając treść kodu 🙂
    A z tym konkursem to niezły numer. Zabrakło propagacji (wykop.pl lub inne place zabaw, tylko nie wiem, czy wiedzieliby o co chodzi…)

  2. Trochę niefortunny przykład. Ponieważ to funkcja, to możesz z niej wyjść w momencie napotkania podzielnika, zwracając False. W tym przypadku zamiast break byłoby return False. I oczywiście na samym końcu funkcji return True. Zupełnie bez użycia else.

Leave a Comment

Komentarze mile widziane.

Jeżeli chcesz do komentarza wstawić kod, użyj składni:
[code]
tutaj wstaw swój kod
[/code]

Jeżeli zrobisz literówkę lub zmienisz zdanie, możesz edytować komentarz po jego zatwierdzeniu.