Podczas tworzenia oprogramowania, rzadko kiedy piszemy cały kod naraz i uruchamiamy go dopiero na końcu. Zazwyczaj proces ten wygląda tak, że piszemy fragment kodu, uruchamiamy go, następnie dodajemy kolejny fragment i powtarzamy te czynności aż do ukończenia projektu.
Skuteczne podejście do tworzenia programu polega na dzieleniu go na mniejsze, łatwiejsze do zarządzania części. Skupiamy się na istotnych fragmentach, pomijając na chwilę inne, do których wracamy później, aby je uzupełnić. W języku Python, aby efektywnie realizować takie podejście, należy posłużyć się instrukcją `pass`. To właśnie ona jest tematem tego artykułu.
Czym jest instrukcja `pass`?
W przeciwieństwie do większości słów kluczowych, które nakazują interpreterowi wykonanie określonej czynności, instrukcja `pass` jest wyjątkowa, ponieważ informuje go, by nie robił nic. Używana jest wewnątrz bloków kodu.
Bloki kodu w Pythonie to wiersze tekstu wcięte pod definicjami funkcji, klas lub instrukcji sterujących przepływem. Instrukcje sterowania przepływem modyfikują standardowy sposób wykonywania programu od góry do dołu, poprzez pomijanie fragmentów kodu w oparciu o warunki lub powtarzanie sekwencji kodu za pomocą pętli. Typowe słowa kluczowe sterowania przepływem w Pythonie to `if`, `for` i `while`.
Dlaczego potrzebujemy instrukcji `pass`?
Jak wspomniałem wcześniej, instrukcja `pass` to instrukcja, która nie robi nic. Pojawia się więc pytanie, po co nam instrukcja, która nic nie robi, skoro budujemy program, który ma wykonywać określone zadania? W tej części wyjaśnię, w jakich sytuacjach instrukcja `pass` znajduje zastosowanie.
#1. Symbol zastępczy dla przyszłej implementacji
Jak już wspomniano na wstępie, podczas programowania bardzo przydatne jest stosowanie strategii „dziel i rządź”. Przykładowo, podczas tworzenia funkcji, możemy chcieć zdefiniować jej nagłówek, a jej treść zaimplementować w późniejszym etapie.
Jednak interpreter Pythona zgłosi błąd, jeśli spróbujemy uruchomić taki kod. Dzieje się tak dlatego, że Python wymaga, aby wewnątrz funkcji lub innego bloku kodu znajdowała się przynajmniej jedna instrukcja. Oto przykład funkcji, która znajduje się w pliku Pythona:
def moja_funkcja(): # Kod zostanie napisany później # Na razie nie ma żadnych instrukcji
Próba uruchomienia tego kodu spowoduje błąd składniowy, o treści podobnej do tej:
File "<ipython-input-1-58189b01193e>", line 3 # Na razie nie ma żadnych instrukcji ^ SyntaxError: incomplete input
Nasza strategia „dziel i rządź” nie będzie działać, jeśli będziemy musieli wszystko pisać od razu, a Python wymaga, abyśmy przynajmniej coś napisali. W tej sytuacji pomocna okazuje się instrukcja `pass`. Z technicznego punktu widzenia jest to instrukcja, a więc jeśli umieścimy ją wewnątrz bloku kodu, Python nie zgłosi błędu. Jednocześnie instrukcja ta nic nie robi, więc nie musimy się martwić o logikę funkcji. Oto poprzednia funkcja, uzupełniona o instrukcję `pass`:
def moja_funkcja(): # Kod zostanie napisany później # Na razie używamy tylko instrukcji pass pass
Teraz, po uruchomieniu kodu, nie powinniśmy otrzymać żadnego błędu.
Możemy również wywołać tę funkcję, aby potwierdzić, że nic ona nie robi.
Zasadniczo to właśnie jest główne zastosowanie instrukcji `pass` w Pythonie – jako symbolu zastępczego dla pustych bloków kodu. Może być ona wykorzystywana nie tylko w funkcjach, ale również w wyrażeniach warunkowych, pętlach oraz klasach.
#2. Implementacja klas abstrakcyjnych i interfejsów
Instrukcja `pass` może być również użyta w celu zaimplementowania klas abstrakcyjnych. Klasa abstrakcyjna to taka klasa, która definiuje metody abstrakcyjne, czyli metody zadeklarowane, ale nie posiadające implementacji. Sytuacja ta jest podobna do wspomnianego wcześniej przypadku, w którym instrukcja `pass` pełniła rolę symbolu zastępczego. Jednak w przeciwieństwie do poprzedniego przypadku, gdzie `pass` była używana tymczasowo, tutaj jej użycie ma charakter trwały.
Klasy abstrakcyjne to klasy bazowe, które definiują metody, które powinny być zaimplementowane przez klasy dziedziczące po nich. Klasy abstrakcyjne nie implementują żadnej logiki, a jedynie określają metody, które powinny być obecne w klasach pochodnych. W rezultacie nie tworzymy bezpośrednio instancji klasy bazowej.
W języku Python do tworzenia klas abstrakcyjnych wykorzystuje się dekorator `@abstractmethod` oraz klasę `ABC`, zdefiniowaną w module `abc`. Jeśli nie pamiętasz lub nie wiesz, czym są dekoratory, zachęcam do zapoznania się z odpowiednim artykułem na ten temat.
Jak już wspomniałem, moduł `abc` definiuje dekorator `@abstractmethod` oraz klasę `ABC`. Użyjemy ich w następujący sposób:
from abc import (abstractmethod, ABC) class KlasaBazowa(ABC): @abstractmethod def metoda_bazowa(self): # Metoda bazowa to metoda, która powinna być zaimplementowana przez każdą klasę dziedziczącą po KlasaBazowa # W tym miejscu ją tylko definiujemy, ale nie implementujemy # W ciele metody używamy instrukcji pass, aby kod był poprawny pass
Klasa `KlasaBazowa` dziedziczy po klasie `ABC`. Ponadto, metoda `metoda_bazowa` została oznaczona dekoratorem `@abstractmethod`. Teraz możemy utworzyć klasę dziedziczącą po `KlasaBazowa` i zaimplementować metodę `metoda_bazowa`.
class KlasaPochodna(KlasaBazowa): def metoda_bazowa(self): print("Witaj z zaimplementowanej metody bazowej")
Następnie możemy utworzyć instancję tej klasy i sprawdzić, czy metoda `metoda_bazowa` działa.
obiekt = KlasaPochodna() obiekt.metoda_bazowa()
Po uruchomieniu tego kodu na ekranie powinna pojawić się odpowiednia wiadomość.
Witaj z zaimplementowanej metody bazowej
#3. Ignorowanie przechwyconych wyjątków
Kiedy w programie napisanym w Pythonie pojawi się błąd, zgłaszany jest wyjątek. Wyjątki są problematyczne, ponieważ prowadzą do zatrzymania działania programu. Możliwe jest jednak przechwytywanie i obsługa wyjątków, co zapobiega awarii aplikacji. Instrukcję `pass` można wykorzystać w sytuacji, gdy nie chcemy podejmować żadnych konkretnych działań w odpowiedzi na błąd. Oto przykład:
try: # Kod, który na pewno spowoduje wyjątek raise Exception('Pewien wyjątek') except: pass
Jeśli uruchomimy powyższy kod, nic się nie wydarzy. Dzieje się tak, ponieważ wyjątek jest zgłaszany, a następnie obsługiwany przez kod w bloku `except`. Jednak ten kod nic nie robi, dlatego też nic się nie dzieje. Zazwyczaj w przypadku wyjątków chcemy je logować lub obsługiwać w bardziej inteligentny sposób. Jeżeli jednak nie chcemy robić nic, to właśnie w taki sposób możemy to osiągnąć.
Czym instrukcja `pass` różni się od `break` i `continue`?
Innymi słowami kluczowymi, z którymi możemy się spotkać są `break` i `continue`. Krótko wyjaśnię, czym się one zajmują, co pomoże odróżnić je od instrukcji `pass`.
Instrukcja `break`
Instrukcja `break` służy do natychmiastowego przerwania wykonywania pętli. Wszystkie kolejne iteracje pętli są anulowane. Przykładowo, załóżmy, że piszemy funkcję wyszukiwania liniowego. Gdy znajdziemy szukany element, nie ma sensu dalej przeszukiwać listy. W takiej sytuacji użycie instrukcji `break` byłoby uzasadnione. Oto przykładowa funkcja wyszukiwania liniowego:
def wyszukiwanie_liniowe(wartosci, szukana_wartosc): for i in range(len(wartosci)): if wartosci[i] == szukana_wartosc: print("Wartość znaleziona na pozycji", i) break
Instrukcja `continue`
Instrukcja `continue` służy do pominięcia bieżącej iteracji w pętli. Jeżeli iterujemy po liście liczb i program napotka instrukcję `continue`, bieżąca iteracja zostaje przerwana, a wykonywanie pętli przechodzi do następnej iteracji. Pętla nadal jest wykonywana. Poniżej znajduje się przykładowa funkcja, która wykorzystuje instrukcję `continue`. Program podwaja wszystkie liczby nieparzyste, a więc lista zawiera tylko liczby parzyste.
def parzyste_liczby(numery): for i in range(len(numery)): if numery[i] % 2 == 0: # Jeżeli liczba jest już parzysta, przechodzimy do następnej iteracji za pomocą continue continue # Tylko liczby nieparzyste zostaną przetworzone w tym miejscu # Podwajamy liczbę, aby stała się parzysta numery[i] *= 2
Mam nadzieję, że dzięki wyjaśnieniu działania instrukcji `break` i `continue`, udało się odróżnić je od instrukcji `pass`.
Dobre praktyki dotyczące stosowania instrukcji `pass`
✅ Należy pamiętać, że instrukcja `pass` najczęściej używana jest jako tymczasowy symbol zastępczy. Nie należy zapominać o zastąpieniu jej docelowym kodem, gdy będziemy na to gotowi.
✅ Jeżeli wykorzystujemy instrukcję `pass` w celach innych niż tymczasowy symbol zastępczy, należy dodać komentarz wyjaśniający, dlaczego została użyta.
Podsumowanie
W tym artykule wyjaśniłem działanie instrukcji `pass` w Pythonie. Jest to bardzo przydatne słowo kluczowe, które umożliwia stosowanie strategii „dziel i rządź” podczas pisania kodu. Instrukcja `pass` jest również opisana w dokumentacji Pythona.
Zachęcam do zapoznania się z informacjami na temat typowych błędów języka Python i sposobów ich rozwiązywania.
newsblog.pl
Maciej – redaktor, pasjonat technologii i samozwańczy pogromca błędów w systemie Windows. Zna Linuxa lepiej niż własną lodówkę, a kawa to jego główne źródło zasilania. Pisze, testuje, naprawia – i czasem nawet wyłącza i włącza ponownie. W wolnych chwilach udaje, że odpoczywa, ale i tak kończy z laptopem na kolanach.