Výčtový typ
Výčtový typ (Enum) slouží k výčtu nějakého konečného počtu hodnot. Například názvy dnů v týdnu, výčet barev, typů platby na nějakém platebním portálu atp. Python podporuje Enum až od verze 3.4, takže tato kapitola se Pythonu 2.7 netýká.
Enum
Výčtový typ se vytváří děděním z enum.Enum
, tj. z třídy Enum
z modulu enum
. Moduly budou popsány v jedné z dalších kapitol. Prozatím vám stačí vědět,
že musíte Enum
importovat pomocí řádky from enum import Enum
.
class Barvy(Enum):
red = "Cervena"
blue = "#0000FF"
black = 0
red
, blue
a black
v příkladu jsou jména, kterým jsou přiřazeny
(za rovnítkem) nějaké hodnoty.
Jak vidíte v příkladu, hodnota může být různého typu. Použití různých typů není ale obvykle dobrý nápad a hodnota výčtového typu vás ani většinou nezajímá. Rozumější příklad může vypadat takto:
class DenTydnu(Enum):
po = 1
ut = 2
st = 3
ct = 5
pa = 6
so = 7
ne = 8
Výčtový typ není lecjaká obyčejná třída. Má několik speciálních vlastností.
Třída výčtového typu je iterovatelná:
[<DenTydnu.po: 1>, <DenTydnu.ut: 2>, <DenTydnu.st: 3>, <DenTydnu.ct: 5>, <DenTydnu.pa: 6>, <DenTydnu.so: 7>, <DenTydnu.ne: 8>]
Členy výčtového typu mají jen jednu instanci (můžete se spolehnout na operátor is):
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python3.4/enum.py", line 292, in __setattr__
raise AttributeError('Cannot reassign members.')
AttributeError: Cannot reassign members.
Člen výčtového typu je potomkem svého výčtového typu:
True
Člen výčtového typu je třída, která má atributy name
a value
.
Člen výčtového typu se nerovná své hodnotě!
False
>>> DenTydnu.po.value == 1
True
>>> DenTydnu.po.name
'po'
Z toho taky plyne, že výčtové typy můžete porovnávat na rovnost a nerovnost, ale ne na "větší" a "menší".
False
>>> DenTydnu.po > DenTydnu.ut
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: DenTydnu() > DenTydnu()
Členové dvou výčtových typů se sobě nerovnají, ikdyž mají stejnou hodnotu:
le = 1
un = 2
br = 3
du = 4
...
False
>>> Mesic.le.value == DenTydnu.po.value
True
IntEnum
Výčtový typ může také dědit z enum.IntEnum
. V takovém případě jsou členové výčtového typu
také potomky int
, tj. můžete s nimi zacházet jako s čísly.
class DenTydnu(IntEnum):
po = 1
ut = 2
st = 3
ct = 5
pa = 6
so = 7
ne = 8
class Mesic(IntEnum):
le = 1
un = 2
br = 3
du = 4
...
True
>>> DenTydnu.po == Mesic.le
True
>>> DenTydnu.po == 1
True
>>> den = DenTydnu.ut
>>> print(["Pondeli","Uteri","Streda"][den-1])
Uteri
>>> list(DenTydnu)
[<DenTydnu.po: 1>, <DenTydnu.ut: 2>, <DenTydnu.st: 3>, <DenTydnu.ct: 5>, <DenTydnu.pa: 6>, <DenTydnu.so: 7>, <DenTydnu.ne: 8>]
>>> DenTydnu.po.value
1
>>> DenTydnu.po.name
'po'
Je doporučováno používat Enum
spíše než IntEnum
, právě kvůli tomu, že se IntEnum
chová spíše jako číslo než jako Enum
(můžete ho porovnávat s jiným číslem nebo s jiným IntEnum členem, na nerovnost).
Většinou je špatně, že se pondělí rovná lednu …