Lekce 4 - Hrací kostka v Pythonu podruhé - Překrývání metod a random
V minulé lekci, Hrací kostka v Pythonu - Zapouzdření a konstruktor, jsme začali vytvářet první pořádný objekt, byla jím hrací kostka.
V tomto tutoriálu objektově orientovaného programování v Pythonu budeme pokračovat v tvorbě naší objektové hrací kostky. Začneme s metodou pro hod. Vysvětlíme si na ní blíže vnitřní import a poté důkladně prozkoumáme principy překrývání metod.
Náhodná čísla
Začneme tím, že ve třídě Kostka
definujeme další metodu.
Nazveme ji hod()
. Metoda nám vrátí náhodné číslo od jedné
do počtu stěn a nebude mít žádný parametr. Náhodné číslo získáme za
pomoci modulu random
. Modul si naimportujeme
vnitřně jako privátní (použijeme jedno
podtržítko) a použijeme metodu randint()
:
def hod(self): """ Vykoná hod kostkou a vrátí číslo od 1 do počtu stěn. """ import random as _random return _random.randint(1, self._pocet_sten)
Použití jednoho podtržítka před názvem importovaného modulu (nebo jakékoliv jiné proměnné) je - nám už známou - konvencí v Pythonu, která signalizuje, že tato proměnná by měla být považována za privátní a neměla by být přímo přistupována mimo třídu nebo modul.
Vnitřní import
Výraz "vnitřní import" se vztahuje k praxi importování modulu přímo uvnitř funkce nebo metody, místo toho, aby byl importován na začátku souboru. V některých případech to přijde vhod, zejména pokud:
- modul potřebujeme jen v určitých specifických situacích,
- import modulu je nákladný na paměť a čas a nechceme, aby zpomaloval start aplikace.
Je důležité si uvědomit, že importování modulu v Pythonu je relativně nákladná operace. Ovšem pouze poprvé, kdy je modul importován. Další pokusy o jeho importování jsou už velmi rychlé, protože Python použije již načtenou verzi modulu z paměti. Jinými slovy, při importování modulů se Python podívá, jestli byl již modul importován. Pokud ano, Python ho znovu neimportuje. Tudíž se první řádek v metodě provede jen jednou. Importy na začátku souboru, jak jsme zvyklí, jsou téměř za všech okolností jednodušším a lepším řešením. Tento koncept tedy berte jen jako ukázku možností jazyka.
Nadměrné používání vnitřních importů kód komplikuje a snižuje jeho čitelnost. Dobrou praxí je tedy používat je uváženě a jen v situacích, kdy přinášejí skutečné výhody.
Překrývání metody
__str__()
Kostka je téměř hotová. Ukažme si teď ještě jednu užitečnou metodu,
kterou budeme hojně používat i ve většině našich dalších objektů.
Řeč je o metodě __str__()
. Tuto metodu obsahuje
každý objekt, tedy i nyní naše kostka. Metoda je určena k
tomu, aby vrátila tzv. textovou reprezentaci instance. Hodí
se ve všech případech, kdy si instanci potřebujeme vypsat nebo s ní
pracovat jako s textem. Tuto metodu mají např. i čísla. V Pythonu funguje
implicitní konverze. Jakmile tedy budeme chtít do konzole
vypsat číslo nebo kterýkoli jiný objekt, Python na něm zavolá metodu
__str__()
a vypíše její výstup. Pokud si děláme vlastní
třídu, měli bychom zvážit, zda se nám takováto metoda hodí. Nikdy bychom
si neměli dělat vlastní metodu, např. něco jako vypis()
, když
už máme v Pythonu připravenou cestu, jak toto řešit. U kostky nemá
__str__()
vyšší smysl, ale u bojovníka bude jistě vracet jeho
jméno. My si ji ke kostce stejně přidáme. Bude vypisovat, že se jedná o
kostku a vrátí i počet stěn. Nejprve si vypišme do konzole naši instanci
kostky. Do konzole se vypíše pouze cesta k naší třídě:
class Kostka:
"""
Třída reprezentuje hrací kostku.
"""
def __init__(self,pocet_sten=6):
self._pocet_sten = pocet_sten
def vrat_pocet_sten(self):
"""
Vrátí počet stěn kostky.
"""
return self._pocet_sten
def hod(self):
"""
Vykoná hod kostkou a vrátí číslo od 1 do
počtu stěn.
"""
import random as _random
return _random.randint(1, self._pocet_sten)
sestistenna = Kostka()
print(sestistenna)
Ačkoli je metoda již definována a poskytuje nám určitý výstup, chceme
o naší kostce získat podrobnější informace. Nejlépe takové, o kterých
sami rozhodneme, že je vhodné je zobrazit. Toho docílíme tím, že
vestavěnou metodu __str__()
jednoduše definujeme sami znovu a
tím ji překryjeme:
class Kostka:
"""
Třída reprezentuje hrací kostku.
"""
def __init__(self,pocet_sten=6):
self._pocet_sten = pocet_sten
def vrat_pocet_sten(self):
"""
Vrátí počet stěn kostky.
"""
return self._pocet_sten
def hod(self):
"""
Vykoná hod kostkou a vrátí číslo od 1 do
počtu stěn.
"""
import random as _random
return _random.randint(1, self._pocet_sten)
def __str__(self):
"""
Vrací textovou reprezentaci kostky.
"""
return str(f"Kostka s {self._pocet_sten} stěnami.")
sestistenna = Kostka()
desetistenna = Kostka(10) # nebo můžeme zapsat Kostka(pocet_sten=10)
print(sestistenna)
print(desetistenna)
V konzoli uvidíme:
Překrytí metody __str__():
Kostka s 6 stěnami.
Kostka s 10 stěnami.
Ještě si naše kostky vyzkoušíme. Zkusíme si v programu s našimi dvěma kostkami v cyklech házet a podíváme se, jestli fungují tak, jak se očekává. Upravíme konec souboru:
class Kostka:
"""
Třída reprezentuje hrací kostku.
"""
def __init__(self,pocet_sten=6):
self._pocet_sten = pocet_sten
def vrat_pocet_sten(self):
"""
Vrátí počet stěn kostky.
"""
return self._pocet_sten
def hod(self):
"""
Vykoná hod kostkou a vrátí číslo od 1 do
počtu stěn.
"""
import random as _random
return _random.randint(1, self._pocet_sten)
def __str__(self):
"""
Vrací textovou reprezentaci kostky.
"""
return str(f"Kostka s {self._pocet_sten} stěnami.")
# vytvoření kostek
sestistenna = Kostka()
desetistenna = Kostka(10)
#hod šestistěnnou
print(sestistenna)
for _ in range(6):
print(sestistenna.hod(), end=" ")
#hod desetistěnnou
print("\n", desetistenna, sep=" ")
for _ in range(10):
print(desetistenna.hod(), end=" ")
Za for
následuje podtržítko. Divné, že? V
kontextu smyčky for
se jednoduché podtržítko _
používá jako dočasná proměnná, když nás skutečná hodnota v každém
průchodu smyčkou nezajímá. Je to konvenční způsob, jak naznačit, že
hodnota této proměnné nebude v daném kontextu využita.
Výstup může vypadat nějak takto:
Konzolová aplikace
Kostka s 6 stěnami
1 6 4 5 5 4
Kostka s 10 stěnami
5 7 3 2 5 10 7 8 3 9
Máme hotovou docela pěknou a nastavitelnou třídu, která reprezentuje hrací kostku. Bude se nám hodit v naší aréně, ale k dispozici ji máme k využití i kdekoli jinde. Vidíme, jak OOP umožňuje znovu používat komponenty.
V následující lekci, Zapouzdření atributů podrobně v Pythonu, se budeme podrobněji věnovat práci s privátními atributy a jejich zapouzdřením.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 204x (898 B)
Aplikace je včetně zdrojových kódů v jazyce Python