Výčty, známé také jako enumerace, představují populární datový typ v programovacích jazycích jako C, C++ a Java. Umožňují vytvářet kód, který je typově bezpečný a snadno čitelný.
V Pythonu nebyla podpora výčtů vždy standardem. Nicméně, od verze 3.4, Python nativně výčty podporuje. Tento článek vám poslouží jako průvodce, jak definovat výčty, jak je využívat a jak přispívají ke zlepšení srozumitelnosti vašeho kódu.
Co jsou to výčty a jaké mají využití?
Výčet (enum) je datový typ, jehož hodnoty jsou definovány předem stanovenou množinou. Tato množina je označována jako sada jeho členů. Výčty umožňují přesněji specifikovat povolené hodnoty proměnné, což vede k typově bezpečnějšímu kódu. Zásadně také přispívají ke zlepšení čitelnosti.
Klíčové pojmy, které je třeba znát
Při diskuzi o výčtech se často setkáme s určitými termíny, které si vyžadují definici. Jedná se zejména o členy a hodnoty výčtu.
- Členové: Jde o pojmenované konstanty, které tvoří sadu možných hodnot daného výčtu. Například, výčet pro dny v týdnu by mohl obsahovat členy jako pondělí, úterý, středa atd.
- Hodnoty: Interní reprezentace každého člena výčtu, která se používá k jednoznačnému rozlišení jednotlivých členů. Například, v našem výčtu dnů může mít pondělí hodnotu 1, úterý hodnotu 2, středa hodnotu 3, a tak dále.
Nyní se podíváme na to, jak výčty zlepšují váš kód.
Jak výčty zkvalitňují váš kód?
Výčty výrazně zlepšují kód tím, že zvyšují jeho čitelnost a snižují riziko chyb. Zde je několik důvodů, proč byste měli výčty používat:
- Výčty umožňují explicitně definovat, jaké hodnoty proměnná nebo argument funkce očekává. Toto vyjasnění záměru u argumentů proměnných nebo funkcí usnadňuje ostatním pochopení vašeho kódu.
- Výčty dělají váš kód samovysvětlujícím. To znamená, že nemusíte přidávat komentáře nebo rozsáhlou dokumentaci, abyste definovali, jaké hodnoty daná funkce přijímá. Samotný výčet specifikuje očekávané hodnoty.
- Použití výčtů také umožňuje IDE detekovat chyby při předávání neplatných hodnot a poskytuje podporu pro automatické dokončování kódu.
- Díky tomu se váš kód stává typově bezpečnějším a minimalizuje se pravděpodobnost chyb za běhu programu.
Dále si ukážeme, jak v Pythonu vytvářet výčty.
Jak vytvořit výčty v Pythonu
Python nemá nativní podporu výčtů přímo v jazyce, ale nabízí modul `enum` ve standardní knihovně. Tento modul budeme v tomto tutoriálu používat. Existují dva hlavní způsoby, jak definovat výčty v Pythonu: pomocí tříd nebo funkčního API. Oběma metodám se budeme v této části věnovat.
Požadavky
Pro postupování podle tohoto tutoriálu potřebujete mít nainstalovaný Python 3.4 nebo novější. Tato verze Pythonu zahrnuje modul `enum` ve standardní knihovně. Pokud ho ještě nemáte, následujte tento návod k instalaci Pythonu.
Dále je pro pochopení konceptů a kódu v tomto tutoriálu potřeba znát základy jazyka Python a pokročilejší koncepty objektově orientovaného programování, jako jsou třídy a dědičnost.
#1. Metoda pomocí tříd
První způsob, jak vytvořit výčet, je definování třídy, která dědí z třídy `Enum` z modulu `enum`. Nejdříve tedy importujeme třídu `Enum`. Následně vytvoříme naši třídu výčtu, která z této třídy dědí.
from enum import Enum class Direction(Enum): NORTH = 0 EAST = 1 SOUTH = 2 WEST = 3
Hodnoty, které jsou členům výčtu přiřazeny, mohou být libovolné. Například, namísto použití hodnot 0, 1, 2 a 3 pro směr, můžeme jim přiřadit odpovídající hodnoty úhlů 0, 90, 180 a 270.
from enum import Enum class Direction(Enum): NORTH = 0 EAST = 90 SOUTH = 180 WEST = 270
Alternativně, lze k generování těchto hodnot použít funkci `range`, což je kratší a přehlednější způsob. Následující kód ukazuje příklad:
from enum import Enum class Direction(Enum): NORTH, EAST, SOUTH, WEST = range(0, 360, 90)
V tomto případě použijeme funkci `range` pro generování hodnot. Začínáme hodnotou 0, končíme 360 a inkrementujeme o 90. Hodnoty z iterovatelné struktury poté destrukturujeme, podobně jako destrukturujeme n-tice. Pokud máte zájem o podrobnosti ohledně destrukturování n-tic, můžete si přečíst článek o n-ticích v Pythonu.
Třídy `Enum` jsou abstraktní třídy, což znamená, že nemají být instanciovány. Místo toho, jejich atributy, v tomto případě reprezentující členy výčtu, jsou dostupné přímo.
#2. Funkční metoda
Alternativou k podtřídění je funkční metoda.
from enum import Enum Direction = Enum("Direction", ["NORTH", "EAST", "SOUTH", "WEST"])
V tomto úryvku kódu definujeme výčet nazvaný `Direction`. Je přístupný skrze čtyři členy, které jsou uvedeny jako druhý argument funkce `Enum`. Implicitně mají tyto členy hodnoty počínající 1. Sever má tedy hodnotu 1, východ 2 atd. Tato hodnota je z důvodu pravdivosti odlišná od indexování od nuly. Všechny hodnoty jsou tak pravdivé.
Alternativně můžete přiřadit členům konkrétní hodnoty pomocí seznamu n-tic. Každá n-tice obsahuje název člena a jeho hodnotu.
from enum import Enum Direction = Enum( name = "Direction", values = [ ("NORTH", "n"), ("EAST", "e"), ("SOUTH", "s"), ("WEST", "w"), ] )
Všimněte si, že při přiřazování hodnot členům jsem použil řetězce namísto celých čísel. Toto demonstruje, že řetězce jsou stejně platné pro přiřazování hodnot jako celá čísla.
Jak používat výčty
V předchozí části jsme si ukázali, jak vytvářet výčty a přiřazovat jim hodnoty. Nyní se budeme zabývat používáním výčtů pro přístup k jejich členům, přiřazování a testování rovnosti.
Jak přistupovat k členům
Existuje několik způsobů, jak přistupovat k členům výčtu. Patří mezi ně tečková notace, přístup pomocí závorek a přístup pomocí hranatých závorek. Následující kód demonstruje všechny tyto metody:
from enum import Enum # Vytvoření výčtu class Day(Enum): SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY = range(1, 8) # Přístup k členům výčtu # 1. Použití tečkové notace print(Day.SUNDAY) # 2. Použití hranatých závorek print(Day["MONDAY"]) # 3. Použití závorek print(Day(3))
Po přístupu k členu výčtu, ho můžete uložit do proměnné. Je důležité si uvědomit, že přístup k členu vám poskytne referenci k objektu člena, nikoliv k jeho hodnotě nebo názvu. Na to je potřeba myslet v následujících sekcích.
Přístup k názvu a hodnotě
Jak bylo zmíněno dříve, když přistupujete k členu výčtu, získáte referenci k objektu člena. Pokud potřebujete získat přístup k názvu nebo hodnotě objektu, můžete použít atributy `name` a `value`.
print(Day.SUNDAY.name, Day.SUNDAY.value)
Kontrola rovnosti
Připomeňme, že přiřazení člena výčtu proměnné vytvoří odkaz na objekt daného člena. Pro ověření, zda proměnná obsahuje konkrétní člen výčtu, musíme použít operátor `is` ke kontrole, zda proměnná a člen výčtu odkazují na stejný objekt.
Zde je příklad:
today = Day.WEDNESDAY if today is Day.MONDAY: print("Je pondělí, :(") if today is Day.WEDNESDAY: print("Šťastnou středu")
Alternativně můžete použít operátor `==`. U nadtříd třídy `Enum` je operátor `==` obalem pro operátor `is`. Toto je implementováno pomocí přetížení operátorů. Více informací o přetížení operátorů si můžete přečíst v tomto článku o Magických metodách. Následuje příklad s operátorem `==` namísto `is`.
today = Day.WEDNESDAY if today == Day.MONDAY: print("Je pondělí, :(") if today == Day.WEDNESDAY: print("Šťastnou středu")
Je důležité si uvědomit, že porovnávání výčtů ověřuje identitu objektu, nikoli jeho hodnotu.
Závěrečná slova
Tento článek se zabýval tím, co jsou výčty a proč jsou užitečné. Prošli jsme si také různé metody vytváření výčtů – podtříděním třídy `Enum` a použitím funkčního API.
Kromě toho jsme se naučili, jak výčty používat, jak přistupovat k hodnotám a provádět srovnání. Nyní byste se mohli chtít podívat na náš článek o výčtech v TypeScriptu.