NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 3 - Hrací kostka v Pythonu - Zapouzdření a konstruktor

V předešlém cvičení, Řešené úlohy k 1.-2. lekci OOP v Pythonu, jsme si procvičili nabyté zkušenosti z předchozích lekcí.

V tomto tutoriálu objektově orientovaného programování v Pythonu začneme pracovat na slíbené aréně, ve které budou proti sobě bojovat dva bojovníci. Boj bude tahový (na přeskáčku) a bojovník vždy druhému ubere život na základě síly jeho útoku a obrany druhého bojovníka. Simulujeme v podstatě stolní hru a budeme tedy simulovat i hrací kostku, která dodá hře prvek náhodnosti. Začněme zvolna a vytvořme si dnes právě tuto hrací kostku. Zároveň se naučíme jak definovat vlastní konstruktor.

Vytvoření projektu

Vytvoříme si nový projekt a pojmenujeme ho TahovyBoj. V projektu vytvoříme nový soubor kostka.py a v něm třídu s názvem Kostka. Zamysleme se nad atributy, které kostce dáme. Jistě by se hodilo, kdybychom si mohli zvolit počet stěn kostky (klasicky 6 nebo 10 stěn, jak je zvykem u tohoto typu her). Naše třída proto bude mít atribut pocet_sten.

Minule jsme kvůli jednoduchosti nastavovali všechny atributy naší třídy jako veřejně přístupné. Většinou se však spíše nechce, aby se daly zvenčí modifikovat. Proto se nastavují jako soukromé. Soukromé atributy začínají jedním nebo dvěma podtržítky. Jedním podtržítkem není přístup odepřen, ale dáváme najevo, že daný prvek se nemá z vnější používat. Dvě podtržítka způsobí, že k atributu poté nelze normálně přistupovat.

My budeme v kurzu používat jedno podtržítko.

Při návrhu třídy tedy použijeme pro atributy podtržítka. Nepoužijeme je pouze v případě, že něco bude opravdu potřeba vystavit. Naše třída nyní vypadá takto:

class Kostka:
    """
    Třída reprezentuje hrací kostku.
    """

Konstruktory

Až doposud jsme neuměli zvenčí nastavit jiné atributy než veřejné, protože soukromé atributy nejsou zvenčí viditelné. Již jsme si říkali něco málo o konstruktoru objektu. Je to metoda, která se zavolá ve chvíli vytvoření instance objektu. Slouží k nastavení vnitřního stavu objektu a k provedení případné inicializace. Kostku nyní vytvoříme takto:

kostka = Kostka()

Právě Kostka() je konstruktor. Protože v naší třídě žádný není, Python si sám vygeneruje prázdnou metodu. My si však nyní konstruktor do třídy přidáme. Deklaruje se jako metoda. V Pythonu můžeme použít metody hned dvě. Metodu __new__() a metodu __init__(). Ta první se volá při vytváření objektu, ale většinou si vystačíme se druhou metodu, která se volá při inicializaci objektu.

Popis rozdílu mezi oběma metodami vyžaduje výrazně hlubší znalosti principů OOP, než kterými zatím disponujeme. Většina programátorů v Pythonu nikdy nepotřebuje přepsat metodu __new__(). Drtivá většina tříd potřebuje pouze __init__() k nastavení počátečního stavu objektu. Pokud si tedy nejsme odůvodněně jistí, zda potřebujeme __new__(), tak ji nepotřebujeme :-)

Vraťme se tedy k metodě __init__(). Jako první parametr píšeme self. Pokud v metodě __init__() jen tak vytvoříme nějakou proměnnou, tak ta po ukončení metody zaniká. My ale potřebujeme vytvořit atribut pocet_sten, který chceme dále používat. Atributy objektů se vytvářejí všemocným slůvkem self. Za self následuje tečka a název atributu. Vytvoříme tedy veřejný atribut pocet_sten:

def __init__(self):
    self.pocet_sten = 6

Pokud kostku nyní vytvoříme, bude atribut pocet_sten nastaven na 6. Vypišme si počet stěn do konzole, ať vidíme, že tam hodnota opravdu je:

Klikni pro editaci
  • class Kostka:
        """
        Třída reprezentuje hrací kostku.
        """
    
        def __init__(self):
            self.pocet_sten = 6
    
    
    kostka = Kostka()
    print(kostka.pocet_sten)
    • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

    V konzoli vidíme výstup:

    Atribut pocet_sten:
    6

    Zapouzdření

    Není dobré atribut pocet_sten nastavit jako veřejný, protože nechceme, aby nám někdo mohl již u vytvořené kostky počet stěn měnit. Přidáme do třídy tedy metodu vrat_pocet_sten(), která nám vrátí hodnotu atributu pocet_sten a tento atribut upravíme na neveřejný pomocí podtržítka. Docílíme tím v podstatě toho, že je atribut označený jako read-only (atribut bychom měli pouze číst metodou). Aby byl skutečně read-only a zvenčí nepřístupný, museli bychom podtržítka použít dvě, ale tím se zatím nebudeme zabývat. Upravená verze třídy i s metodou:

    Klikni pro editaci
    • class Kostka:
          """
          Třída reprezentuje hrací kostku.
          """
      
          def __init__(self):
              self._pocet_sten = 6      # jedno podtržítko dává najevo, že nechceme, aby se k atributu přistupovalo přímo
      
          def vrat_pocet_sten(self):
              """
              Vrátí počet stěn kostky.
              """
              return self._pocet_sten
      
      
      kostka = Kostka()
      print(kostka.vrat_pocet_sten())
      • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

      V konzoli vidíme výstup:

      Výstup metody vrat_pocet_sten():
      6

      Atribut se stal neveřejným díky přidání podtržítka. Navíc jsme změnili vypisování, jelikož hodnotu atributu zjistíme pouze zavoláním metody.

      Volitelný počet stěn

      Vidíme, že se konstruktor opravdu zavolal. My bychom ale chtěli, abychom mohli u každé kostky při vytvoření specifikovat, kolik stěn budeme potřebovat. Dáme tedy konstruktoru parametr:

      def __init__(self, pocet_sten):
          self._pocet_sten = pocet_sten

      Vidíme, že názvy atributu a argumentu jsou skoro stejné. Pokud bychom měli počet stěn jako veřejný atribut, stejný název nevadí. Pomocí self specifikujeme, že levá proměnná pocet_sten náleží instanci, pravou Python chápe jako předanou z parametru (argumentu). S veřejným atributem by situace vypadala takto:

      def __init__(self, pocet_sten):
          self.pocet_sten = pocet_sten

      Vraťme se však k původnímu kódu a zkusme si zadat parametr do konstruktoru:

      Klikni pro editaci
      • kostka = Kostka(10) # v tuto chvíli se zavolá konstruktor s par. 10
        print(kostka.vrat_pocet_sten())
        • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

        V konzoli vidíme výstup:

        Výstup s parametrem konstruktoru 10:
        10

        Výchozí hodnota kostky

        Vše funguje, jak jsme očekávali. Python nám již v tuto chvíli nevygeneruje prázdný (tzv. bezparametrický) konstruktor, takže kostku bez parametru již vytvořit nelze. My to však můžeme umožnit pomocí uvedení výchozí hodnoty argumentu pocet_sten v definici konstruktoru. Nastavíme ji na hodnotu 6. Takovou hodnotu uživatel naší třídy u kostky očekává jako výchozí:

        def __init__(self, pocet_sten=6):
            self._pocet_sten = pocet_sten

        Vytvořme teď dvě instance kostky, jednu bez udání počtu stěn a jednu s ním:

        Klikni pro editaci
        • sestistenna = Kostka()
          desetistenna = Kostka(10) # nebo můžeme zapsat Kostka(pocet_sten=10)
          print(sestistenna.vrat_pocet_sten())
          print(desetistenna.vrat_pocet_sten())
          • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

          Máme tedy konstruktor, který nám umožňuje tvořit různé hrací kostky. Díky klíčovému argumentu nemusíme zadávat počet stěn.

          Toho můžeme využívat i u všech dalších metod, nejen u konstruktorů. Mnoho funkcí a metod v Pythonu má klíčové argumenty, například vestavěná funkce print(). Je dobré si u metod projít jejich klíčové argumenty, abychom neprogramovali něco, co již někdo udělal před námi.

          To je pro dnešní lekci vše.

          V příští lekci, Hrací kostka v Pythonu podruhé - Překrývání metod a random, se naučíme překrývat metody, používat vnitřní import a dokončíme hrací kostku.


           

          Měl jsi s čímkoli problém? Zdrojový kód vzorové aplikace je ke stažení každých pár lekcí. Zatím pokračuj dál, a pak si svou aplikaci porovnej se vzorem a snadno oprav.

          Jak se ti líbí článek?
          Před uložením hodnocení, popiš prosím autorovi, co je špatněZnaků 0 z 50-500
          Předchozí článek
          Řešené úlohy k 1.-2. lekci OOP v Pythonu
          Všechny články v sekci
          Objektově orientované programování v Pythonu
          Přeskočit článek
          (nedoporučujeme)
          Hrací kostka v Pythonu podruhé - Překrývání metod a random
          Článek pro vás napsal gcx11
          Avatar
          Uživatelské hodnocení:
          762 hlasů
          (^_^)
          Aktivity