Efektivní ladění pomocí příkazu Python Assert Statement

Photo of author

By etechblogcz

Jste programátor? Pak je pro vás ladění klíčovou dovedností, bez ohledu na to, v jakém programovacím jazyce tvoříte. V tomto článku se podíváme na to, jak efektivně využívat příkaz `assert` v Pythonu pro ladění kódu.

Při práci na projektu se obvykle setkáváme s více moduly, které obsahují funkce, definice tříd a další prvky. Často se stává, že narazíme na chyby nebo neočekávané výsledky, které jsou způsobeny chybami v implementaci. V takových situacích je velmi užitečné používat příkazy `assert`.

V tomto tutoriálu si objasníme syntaxi pro použití příkazu `assert` a ukážeme si to na konkrétních příkladech. Dále si vysvětlíme, co jsou to chyby asercí a jak nám mohou pomoci při odhalování a opravování chyb v našem kódu během vývoje.

Začněme!

Jak používat příkaz `assert` v Pythonu

Nejprve se zaměříme na syntaxi příkazu `assert` a poté si ukážeme několik praktických příkladů.

Syntaxe příkazu `assert`

Syntaxe pro použití příkazu `assert` v Pythonu vypadá takto:

assert expression, message

Kde:

  • `expression` představuje libovolný platný Pythonovský výraz, který má být vyhodnocen. Může to být například podmínka ověřující hodnotu proměnné, pravdivostní hodnota proměnné nebo návratová hodnota z funkce.
  • Pokud se výraz vyhodnotí jako `True`, příkaz `assert` nevyvolá žádnou chybu ani nic nevrací. To signalizuje, že program pracuje tak, jak by měl.
  • Pokud se výraz vyhodnotí jako `False`, je vyvolána výjimka `AssertionError`.
  • `message` je volitelný řetězec. Můžete zadat zprávu, která se zobrazí ve výpisu zpětného volání (traceback) při vyvolání výjimky `AssertionError`.

Nyní se podíváme na několik praktických příkladů, které demonstrují, jak nám příkaz `assert` může pomoci napsat čistší a bezchybný kód.

Příklady kódu použité v tomto tutoriálu jsou dostupné na GitHubu.

Příklady použití `assert` v Pythonu

Zvažte následující situaci. Představte si, že máte v kódu proměnnou `sleva`, jejíž hodnota by měla být vždy menší nebo rovna maximální povolené slevě `max_sleva`.

Pro ověření, zda omylem nenastavíte proměnnou `sleva` na nepřípustnou hodnotu, můžete použít příkaz `assert` s výrazem: `sleva <= max_sleva`.

>>> max_sleva = 50
>>> sleva = 20
>>> assert sleva <= max_sleva

V tomto případě je `sleva` (20) menší než `max_sleva` (50), takže příkaz `assert` nevyvolá žádnou chybu.

Výjimka `AssertionError`

Pokud je proměnná `sleva` nastavena na hodnotu, která je větší než `max_sleva`, dojde k vyvolání výjimky `AssertionError`.

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

Jak už bylo zmíněno, příkaz `assert` umožňuje zadat volitelný řetězec se zprávou.

Použijme řetězec zprávy s podrobnějšími diagnostickými informacemi. Do příkazu `assert` přidáme f-string, který obsahuje hodnoty `sleva` a `max_sleva`.

>>> assert sleva <= max_sleva, f"Sleva by měla být maximálně {max_sleva}; obdržena sleva = {sleva}"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError: Sleva by měla být maximálně 50; obdržena sleva = 75

Z výstupu je zřejmé, že výjimka `AssertionError` nyní obsahuje hodnoty proměnných `sleva` a `max_sleva`.

Ladění a testování funkcí Pythonu pomocí `assert`

Při definování funkcí může neúmyslně dojít k zavedení chyb (logických chyb), které způsobí, že funkce nepracuje podle očekávání.

Podívejme se na konkrétní příklad. Představte si, že ve třídě probíhá test a studenti mají možnost pokusit se o bonusovou otázku. Každý student, který se pokusí o bonusovou otázku, získá v testu 10 bodů navíc. 😄

Zvažte následující funkci `ziskej_konecny_pocet_bodu`:

  • Jako vstupní parametry přijímá aktuální počet bodů (`body`) a logickou hodnotu (`bonus`).
  • Pokud student odpověděl na bonusovou otázku (tedy `bonus` je `True`), získá 10 bodů navíc k aktuálnímu počtu bodů.
  • Funkce následně vrátí konečný počet bodů.
def ziskej_konecny_pocet_bodu(body, bonus):
    if bonus:
        body += 10
    return body

Pojďme si funkci vyzkoušet s několika různými vstupními parametry. Vidíme, že pro `body` 34 a 40 s `bonus` nastaveným na `True` a `False` jsou konečné výsledky 44, respektive 40.

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

Maximální počet bodů v testu je však například 50. Pokud tedy student dosáhne 49 bodů a zároveň odpoví na bonusovou otázku, funkce `ziskej_konecny_pocet_bodu` s radostí spočítá výsledek na 59.

print(ziskej_konecny_pocet_bodu(49, True))
# 59

Technicky je to možné. Předpokládejme však, že student nemůže získat více bodů, než je maximální počet bodů v testu. 🙂

Inicializujme tedy proměnnou `max_body`. A uložme vrácený počet bodů z funkce do proměnné `konecny_pocet_bodu`.

Následně přidáme příkaz `assert`, který ověří, zda je `konecny_pocet_bodu` menší nebo roven `max_body`.

def ziskej_konecny_pocet_bodu(body, bonus):
    if bonus:
        body += 10
    return body

konecny_pocet_bodu = ziskej_konecny_pocet_bodu(47, True)
max_body = 50

assert konecny_pocet_bodu <= max_body

Nyní obdržíme výjimku `AssertionError` pro volání funkce `ziskej_konecny_pocet_bodu(47, True)`:

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

Nyní přidáme do příkazu `assert` popisný f-řetězec:

assert konecny_pocet_bodu <= max_body, f"konecny_pocet_bodu by měl být maximálně {max_body}; obdrženo {konecny_pocet_bodu}"
Traceback (most recent call last):
  File "main.py", line 17, in <module>
    assert konecny_pocet_bodu <= max_body,f"konecny_pocet_bodu by měl být maximálně {max_body}; obdrženo {konecny_pocet_bodu}"
AssertionError: konecny_pocet_bodu by měl být maximálně 50; obdrženo 57

Úprava funkce

Vraťme se zpět a upravme definici funkce `ziskej_konecny_pocet_bodu`, abychom opravili toto neočekávané chování:

  • Funkce `ziskej_konecny_pocet_bodu` nyní přijímá jako parametr i `max_body`.
  • Ověříme, zda je `bonus` `True`. Pokud ano, přidáme 10 bodů k proměnné `body`.
  • Následně ověříme, zda je `body` větší než `max_body`. Pokud ano, vrátíme `max_body`.
  • V opačném případě vrátíme `body`.

Tímto jsme zajistili, že konečný počet bodů je vždy menší nebo roven `max_body`.

def ziskej_konecny_pocet_bodu(body, bonus, max_body):
    if bonus:
        body += 10
    if body > max_body:
        return max_body
    return body

Pro rychlé procvičení si zkuste napsat několik příkazů `assert`, abyste ověřili, zda funkce nyní funguje podle očekávání.

Poznámka k výjimce `AssertionError`

Ačkoliv k výjimce `AssertionError` dochází, když se výraz vyhodnotí jako `False`, je důležité si pamatovat, že tyto chyby by neměly být řešeny jako výjimky. To znamená, že bychom se měli vyhnout takovému kódu:

try:
    <něco dělám>
except AssertionError:
    <udělej toto>

V předchozím příkladu s funkcí `ziskej_konecny_pocet_bodu` jsme použili `assert` pro ověření, zda je `konecny_pocet_bodu` menší nebo roven `max_body`. Poté jsme upravili definici funkce, abychom eliminovali chyby asercí.

To je skutečný účel příkazů `assert`. Jsou to jakési kontroly zdravého rozumu kódu a pomáhají při psaní čistšího kódu. Na druhou stranu, zpracování výjimek se zaměřuje na předvídání a zpracování neočekávaných chyb za běhu, často se jedná o neplatné typy a hodnoty vstupů.

Shrnuto, měli byste využívat příkaz `assert` v Pythonu pro efektivní ladění a nezpracovávat `AssertionError` jako výjimky.

Závěr

Tento tutoriál vám pomohl pochopit, jak používat příkaz `assert` v Pythonu. Zde je krátké shrnutí toho, co jste se naučili:

  • Příkazy `assert` v Pythonu mají tvar `assert výraz`. Tento příkaz kontroluje, zda je `výraz` `True`. Pokud se `výraz` nevyhodnotí jako `True`, je vyvolána výjimka `AssertionError`.
  • `Assert` lze použít i s tvarem `assert výraz, zpráva`. Tím se vypíše `zpráva` v případě, že dojde k výjimce `AssertionError`.
  • Je důležité si pamatovat, že byste neměli implementovat zpracování výjimek k řešení chyb asercí. Aserce by měly být používány jako užitečný ladicí nástroj pro ověření, zda je váš kód logický.

Jako vývojáři vám aserce pomáhají při ladění. Pro zajištění, že všechny jednotlivé komponenty (moduly) vašeho projektu pracují podle očekávání, se můžete naučit psát unit testy v Pythonu.

Dále se podívejte na tento seznam projektů pro začátečníky v Pythonu, na kterých můžete pracovat.