Skuteczne debugowanie za pomocą instrukcji Assert w języku Python

jesteś programistą? Jeśli tak, debugowanie jest podstawową umiejętnością, niezależnie od języka, w którym kodujesz. W tym artykule dowiesz się, jak używać instrukcji assert w Pythonie do efektywnego debugowania.

Podczas pracy nad projektem zdefiniujesz wiele modułów. Obejmuje to funkcje, definicje klas i nie tylko. I prawdopodobnie napotkasz błędy lub nieoczekiwane wyniki z powodu błędu w implementacji. Instrukcje Assert są pomocne w debugowaniu takiego kodu.

W tym samouczku nauczymy się składni użycia instrukcji assert oraz przykładów kodu, aby zobaczyć ją w akcji. Zobaczymy również, czym są błędy asercji i jak możemy je wykorzystać do naprawienia błędów w kodzie podczas programowania.

Zaczynajmy!

Jak używać instrukcji Assert w Pythonie

Nauczymy się składni instrukcji assert, a następnie przejdziemy do kodowania kilku przykładów.

Składnia instrukcji Assert

Zacznijmy od składni, aby użyć instrukcji assert w Pythonie:

assert expression, message

Tutaj,

  • wyrażenie jest dowolnym prawidłowym wyrażeniem Pythona do oceny. Może to być warunek dotyczący wartości zmiennej, wartości logicznej zmiennej, wartości zwracanej przez funkcję i nie tylko.
  • Dopóki wyrażenie ma wartość True, instrukcja assert nie zgłasza błędu ani niczego nie zwraca. Oznacza to, że program działa zgodnie z oczekiwaniami.
  • Jeśli wyrażenie nie ma już wartości True, zgłaszany jest wyjątek AssertionError.
  • wiadomość jest ciągiem opcjonalnym. Możesz określić komunikat, który będzie wyświetlany w śledzeniu wstecznym za każdym razem, gdy zostanie zgłoszony wyjątek AssertionError.

Następnie przejdźmy do kodowania kilku przykładów, w których instrukcja assert może pomóc nam napisać czystszy i wolny od błędów kod.

Przykłady kodu używane w tym samouczku można znaleźć w tym GitHub Gist.

Przykłady instrukcji Assert w języku Python

Rozważ następujący przykład. Załóżmy, że masz w kodzie zmienną rabatu. Ale chciałbyś, aby jego wartość była zawsze mniejsza lub równa max_discount.

Aby sprawdzić, czy przypadkowo nie ustawiłeś zmiennej rabatu na wartość, możesz dodać asercję. Wyrażenie do obliczenia to: zniżka <= max_discount.

>>> max_discount = 50
>>> discount = 20
>>> assert discount <= max_discount

Tutaj zniżka (20) jest mniejsza niż max_discount (50). Tak więc instrukcja assert nie zgłasza żadnego błędu.

Wyjątek AssertionError

Jeśli zmienna rabatu jest ustawiona na wartość większą niż max_discount, zgłaszany jest wyjątek AssertionError.

>>> discount = 75
>>> assert discount <= max_discount
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError

Wiemy, że instrukcja assert pozwala nam również określić opcjonalny ciąg komunikatu.

Użyjmy również ciągu komunikatów, który zawiera bardziej opisowe informacje diagnostyczne. Do instrukcji assert dodajmy łańcuch f w języku Python, który zawiera również wartości Discount i max_discount.

>>> assert discount <= max_discount, f"discount should be at most {max_discount}; got discount = {discount}"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError: discount should be at most 50; got discount = 75

Jak widać w powyższej komórce wyjściowej, wyjątek AssertionError obejmuje teraz wartości zmiennych Discount i max_discount.

Debugowanie i testowanie funkcji Pythona za pomocą Assert

Podczas definiowania funkcji możesz czasem nieumyślnie wprowadzić błędy (błędy logiczne), które uniemożliwią działanie funkcji zgodnie z przeznaczeniem.

Weźmy przykład. Załóżmy, że w klasie odbywa się test, a uczniowie mają szansę odpowiedzieć na dodatkowe pytanie. Każdy uczeń, który spróbuje odpowiedzieć na dodatkowe pytanie, otrzyma 10 dodatkowych punktów w teście. 😄

Rozważ następującą funkcję get_final_score:

  • Obejmuje bieżący wynik, wynik i premię logiczną.
  • Jeśli uczeń odpowiedział na dodatkowe pytanie, premia logiczna jest równa True i otrzymuje 10 punktów więcej niż jego aktualny wynik.
  • Następnie funkcja zwraca wynik końcowy.
def get_final_score(score,bonus):
    if bonus:
        score += 10
    return score

Wykonajmy kilka wywołań funkcji. Widzimy, że dla wyników 34 i 40 z premią ustawioną na Prawda i Fałsz, końcowe wyniki to odpowiednio 44 i 40.

print(get_final_score(34,True))
# 44
print(get_final_score(40,False))
# 40

Jednak maksymalna liczba punktów w teście wynosi, powiedzmy, 50. Jeśli więc uczeń uzyska 49 punktów i odpowiedział również na pytanie dodatkowe, funkcja get_final_score z radością obliczy końcowy wynik na 59.

print(get_final_score(49,True))
# 59

Technicznie jest to możliwe. Załóżmy jednak, że student nie może zdobyć więcej niż maksymalna możliwa liczba punktów za test. 🙂

Zainicjujmy więc zmienną max_score. I przechwyć zwrócony wynik z funkcji w zmiennej final_score.

Następnie dodajemy asercję, która sprawdza, czy final_score jest mniejszy niż max_score.

def get_final_score(score,bonus):
    if bonus:
        score += 10
    return score

final_score = get_final_score(47,True)
max_score = 50

assert final_score <= max_score

Otrzymujemy teraz wyjątek AssertionError dla wywołania funkcji get_final_score(47,True):

Traceback (most recent call last):
  File "main.py", line 17, in <module>
    assert final_score <= max_score
AssertionError

Teraz dodajemy opisowy f-string do instrukcji asercji Pythona:

assert final_score <= max_score,f"final_score should be at most {max_score}; got {final_score}"
Traceback (most recent call last):
  File "main.py", line 17, in <module>
    assert final_score <= max_score,f"final_score should be at most {max_score}; got {final_score}"
AssertionError: final_score should be at most 50; got 57

Modyfikowanie funkcji

Cofnijmy się i zmodyfikujmy definicję funkcji get_final_score, aby naprawić nieoczekiwane zachowanie:

  • Funkcja get_final_score przyjmuje również max_score jako parametr.
  • Sprawdzamy, czy bonus jest prawdziwy. Jeśli True, do zmiennej punktacji dodajemy 10 punktów.
  • Następnie sprawdzamy, czy wynik jest większy niż max_score. Jeśli tak, zwracamy max_score.
  • W przeciwnym razie zwracamy wynik.

Zapewniliśmy teraz, że końcowy wynik jest zawsze mniejszy lub równy max_score.

def get_final_score(score,bonus,max_score):
    if bonus:
        score += 10
    if score > max_score:
        return max_score
    return score

W ramach szybkiego ćwiczenia napisz kilka stwierdzeń, aby potwierdzić, że funkcja działa teraz zgodnie z oczekiwaniami.

Uwaga dotycząca wyjątku AssertionError

Chociaż wyjątek AssertionError występuje, gdy wyrażenie zwraca wartość False, powinniśmy pamiętać, aby nie traktować takich błędów jako wyjątków. Oznacza to, że nie powinniśmy robić czegoś takiego:

try:
    <doing this>
except AssertionError:
    <do this>

W poprzednim przykładzie get_final_score użyliśmy potwierdzenia, aby sprawdzić, czy final_score jest mniejszy niż max_score. Następnie zmodyfikowaliśmy definicję funkcji tak, aby nie było błędów asercji.

Do tego służą afirmacje. Są to testy poprawności kodu i pomagają w pisaniu czystszego kodu. Z drugiej strony obsługa wyjątków polega na przewidywaniu i obsłudze nieoczekiwanych błędów w czasie wykonywania. Często obejmują one nieprawidłowe typy danych wejściowych i wartości.

Podsumowując, do efektywnego debugowania należy używać instrukcji asert w Pythonie, a nie traktować błędów AssertionErrors jako wyjątków.

Wniosek

Ten samouczek pomógł ci zrozumieć, jak używać instrukcji assert w Pythonie. Oto podsumowanie tego, czego się nauczyłeś:

  • Wyrażenia asercji w języku Python (asercje) mają postać wyrażenia assert. To sprawdza, czy wyrażenie jest prawdziwe. Jeśli nie ma wartości True, zgłaszany jest wyjątek AssertionError.
  • Można również użyć assert ze składnią wyrażenia assert, message. Spowoduje to wydrukowanie ciągu wiadomości za każdym razem, gdy wystąpi wyjątek AssertionError.
  • Należy pamiętać, aby nie implementować obsługi wyjątków do obsługi błędów asercji. I używaj asercji jako pomocnego narzędzia do debugowania do sprawdzania poprawności kodu.

Asercje pomagają programistom w debugowaniu. Aby upewnić się, że wszystkie poszczególne komponenty (moduły) projektu działają zgodnie z oczekiwaniami, możesz nauczyć się pisać testy jednostkowe w Pythonie.

Następnie sprawdź tę listę projektów Pythona dla początkujących, nad którymi możesz pracować.