Zarábaj až 6 000 € mesačne! Akreditované rekvalifikačné kurzy od 0 €. Viac informácií.

20. diel - Magické metódy v Pythone

V predchádzajúcej lekcii, Vlastnosti v Pythone - Pokročilé vlastnosti a dedenie, sme sa v práci s vlastnosťami zamerali na dedenie, časté chyby a vytváranie vlastných dekorátorov pre vlastnosti.

V nasledujúcom tutoriáli objektovo orientovaného programovania v Pythone sa zameriame na magické (dunder) metódy objektov. Znalosť dunder metód nám poskytne hlbšie pochopenie toho, ako Python funguje "pod kapotou". Vďaka tomu budeme schopní lepšie rozumieť správaniu objektov a ich interakciám s jazykovými konštruktmi.

Magické metódy

Magické (dunder) metódy sú kľúčovou súčasťou Pythona a tvoria základ mnohých jeho OOP funkcií. Názov "dunder" pochádza z anglického "double underscore" (dvojité podčiarkovníky), čo odkazuje na ich typický zápis, napríklad __init__() alebo __str__(). Tieto metódy boli do Pythona pridané, aby umožnili vývojárom definovať správanie objektov v rôznych kontextoch, ako je inicializácia, reprezentácia, aritmetické operácie a mnoho ďalších.

S niekoľkými týmito metódami sme sa už stretli, ako napríklad s magickou metódou __init__() na inicializáciu objektu alebo s metódou __str__() na vypísanie jeho ľudsky čitateľnej reprezentácie.

Prehľad magických dunder metód

Dunder metódy si pre lepší prehľad rozdelíme do niekoľkých kategórií podľa ich funkcií:

1. Základné dunder metódy

  • objektová inicializácia a reprezentácia - __init__(), __str__(), __repr__(),
  • operátory porovnanie - __eq__(), __lt__(), __gt__(), a ďalšie,
  • logické operácie - __bool__()
  • matematické operátory - __add__(), __sub__(), __mul__(), __truediv__(), a ďalšie,
  • správa kontextu - __enter__(), __exit__() (pre použitie vo with príkaze).

2. Pokročilé dunder metódy

  • atribútové a indexové operácie - __getattr__(), __setattr__(), __delattr__(), __getitem__(), __setitem__(),
  • volanie objektov - __call__() (premena objektu na volateľný objekt),
  • správa inštancií - __new__() (používa sa na tvorbu nových inštancií).

3. Špeciálne prípady

  • vytvorenie užívateľsky definovaných kontajnerov - __len__(), __getitem__(),
  • custom iterátory a generátory - __iter__() a __next__(),
  • správa pamäte a Garbage Collection - __del__().

Toto je len základný prehľad. V tejto lekcii sa budeme venovať detailne prvej kategórii. Vopred upozorníme, že mnoho dunder metód je hlboko prepojených s kolekciami, ktoré zatiaľ nepoznáme. Zoznámime sa s nimi v kurze Kolekcie v Pythone. Napriek tomu sa v príkladoch kolekciám vyhneme, aby boli čo najviac pochopiteľné. Poďme na to.

Základné dunder metódy

Začneme prehľadom a príklady použitia základných metód.

Objektová inicializácia a reprezentácia

Tieto metódy, ktoré už dobre poznáme, sú základným stavebným kameňom pre akúkoľvek triedu v Pythone.

Metódy __init__(), __str__() a __repr__()

Metódu __init__() Python volá, kedykoľvek vytvárame novú inštanciu triedy. Používa sa na inicializáciu atribútov. Metódy __str__() a __repr__() určujú, ako bude objekt reprezentovaný ako reťazec. Zatiaľ čo __str__() vracia čitateľnú reprezentáciu pre koncových užívateľov, __repr__() má za cieľ poskytnúť jednoznačnú reprezentáciu objektu, ktorá je často technickej povahy a vhodná pre vývojárov. Tu si príklady uvádzať nebudeme, so všetkými spomínanými metódami sme sa už detailne zoznámili skôr.

Operátory porovnanie

Na porovnávacie metódy sa pozrime vo forme tabuľky:

Metóda Slovný popis Reprezentuje kód
__lt__(self, other) menšie ako (less than) x < y
__le__(self, other) menší alebo rovný (less or equal) x <= y
__eq__(self, other) rovná sa (equal) x == y
__ne__(self, other) nerovná sa (not equal) x != y
__gt__(self, other) väčšia ako (greater than) x > y
__ge__(self, other) väčší alebo rovný (greater or equal) x >= y

Všetky porovnávacie metódy vracajú True alebo False, popr. vyvolajú výnimku, ak sa porovnávanie s druhým objektom nepodporuje. Ich syntax je rovnaká:

Klikni pre editáciu
  • class Number:
        def __init__(self, value):
            self.value = value
    
        def __gt__(self, other_number):
            if isinstance(other_number, Number):
                return self.value > other_number.value
            else:
                raise ValueError("Cannot compare 'Number' with an object of a different type.")
    
    pi = Number(3.14)
    e = Number(2.74)
    
    print(pi > e)  # calls pi.__gt__(e), where e is "other"
    
    # Example of an exception when trying to compare 'Number' with 'str'
    other_value = "text"
    try:
        print(pi > other_value)  # raises an exception
    except ValueError as error:
        print(error)  # prints the error message
    • Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.

    Logické operácie

    Metóda pre logické operácie určuje, ako sa má objekt správať v kontexte pravdivostných testov a logických operácií.

    Metóda __bool__()

    Pozrime sa, ako dokážeme prispôsobiť správanie metódy pri prevode objektu na typ bool:

    Klikni pre editáciu
    • class Car:
          def __init__(self, fuel):
              self.fuel = fuel
      
          def __bool__(self):
              # The car is "True" (functional) if it has more than 10 liters of fuel
              return self.fuel > 10
      
      # Testing
      service_car = Car(5)  # Not enough fuel
      my_car = Car(20) # Enough fuel
      
      print(bool(service_car))  # Prints False
      print(bool(my_car))      # Prints True
      • Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.

      V príklade metóda __bool__() kontroluje, či je v nádrži viac ako 10 litrov paliva. Ak áno, vracia True, inak False. Tým je dosiahnuté to, že hodnota bool() na inštancii triedy Car priamo závisí od množstva paliva v nádrži.

      Tento prístup je užitočný v situáciách, keď chceme, aby hodnota bool() objektu reprezentovala jeho stav podľa nejakého špecifického kritéria, ktoré je dôležité pre logiku nášho programu.

      Matematické operátory

      Matematické operátory v Pythone sú skvelým príkladom toho, ako dunder metódy umožňujú objektom reagovať na štandardné matematické operácie. Pozrieme sa na ne opäť vo forme tabuľky:

      Metóda Slovný popis Reprezentuje kód
      __add__(self, other) sčítanie +
      __sub__(self, other) odčítanie -
      __mul__(self, other) násobenie *
      __truediv__(self, other) delenie /
      __eq__(self, other) rovná sa =
      __mod__(self, other) modulo %
      __pow__(self, other[, modulo]) umocňovanie **

      Tieto metódy umožňujú objektom pracovať s aritmetickými operátormi rovnako, ako by to boli bežné číselné typy. Ako príklad si definujeme triedu ComplexNumber, ktorá bude reprezentovať komplexné čísla a bude implementovať súčet:

      Klikni pre editáciu
      • class ComplexNumber:
            def __init__(self, real, imaginary):
                self.real = real
                self.imaginary = imaginary
        
            def __add__(self, other):
                return ComplexNumber(self.real + other.real, self.imaginary + other.imaginary)
        
            def __str__(self):
                return f"{self.real} + {self.imaginary}i"
        
        # Testing
        first_complex = ComplexNumber(1, 2)
        second_complex = ComplexNumber(3, 4)
        
        result = first_complex + second_complex
        print(result)  # Prints "4 + 6i"
        • Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.

        Všetky spomenuté metódy umožňujú preťažiť správanie štandardných operátorov a prispôsobiť ich funkčnosť pre užívateľsky definované objekty.

        Preťaženie operátorov

        Python nám umožňuje modifikovať spôsob, akým štandardné operátory (ako +, -, *, /, <, == a ďalšie) fungujú s našimi vlastnými objektmi. Už sme si ukázali, že pre každý operátor existuje zodpovedajúca metóda. Teraz si ukážeme, ako ju definovať v rámci triedy, aby sa zmenila štandardná funkcionalita daného operátora.

        Vytvoríme si triedu Vector, ktorá reprezentuje 2D vektor a preťažuje niektorých matematických operátorov:

        Klikni pre editáciu
        • class Vector:
              def __init__(self, x_coordinate, y_coordinate):
                  self.x_coordinate = x_coordinate
                  self.y_coordinate = y_coordinate
          
              def __repr__(self):
                  return f"Vector({self.x_coordinate}, {self.y_coordinate})"
          
              def __add__(self, other_vector):
                  # Overloading the + operator
                  return Vector(self.x_coordinate + other_vector.x_coordinate, self.y_coordinate + other_vector.y_coordinate)
          
              def __sub__(self, other_vector):
                  # Overloading the - operator
                  return Vector(self.x_coordinate - other_vector.x_coordinate, self.y_coordinate - other_vector.y_coordinate)
          
              def __mul__(self, scalar_value):
                  # Overloading the * operator for scalar multiplication
                  return Vector(self.x_coordinate * scalar_value, self.y_coordinate * scalar_value)
          
          # Example of usage
          vector1 = Vector(2, 3)
          vector2 = Vector(1, 1)
          print(vector1 + vector2)  # Output: Vector(3, 4)
          print(vector1 - vector2)  # Output: Vector(1, 2)
          print(vector1 * 3)        # Output: Vector(6, 9)
          • Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.

          Správa kontextu

          V Pythone sa správa kontextu využíva hlavne na správne spracovanie zdrojov a na zabezpečenie, že sú tieto zdroje korektne uvoľnené alebo uzavreté po použití. Kľúčovým prvkom pre správu kontextu je využitie príkazu with, ktorý automaticky zaistí správne otvorenie a uzavretie zdrojov, ako sú súbory, sieťové pripojenia a podobne. Táto kapitola je zatiaľ trochu mimo našich obzorov, súbory a sietí sa budeme zaoberať v pokročilejších kurzoch. Napriek tomu vo výčte nesmie chýbať a príklad, ktorý si uvedieme, bude úplne v medziach našich znalostí.

          Metóda __enter__()

          Metóda __enter__() sa zavolá v okamihu, keď kód vstupuje do kontextového manažéra – teda do bloku kódu definovaného príkazom with. Typicky sa v tejto metóde vykonávajú inicializačné operácie, ako je otvorenie súboru alebo získanie zámku.

          Metóda __exit__()

          Metóda __exit__() sa zavolá na konci bloku kódu v príkaze with, bez ohľadu na to, či bol blok opustený normálne, alebo došlo k vyhodeniu výnimky. Táto metóda zvyčajne zahŕňa upratovacie operácie, ako je zatváranie súborov alebo uvoľnenie zdrojov. Má tri argumenty, ktoré reprezentujú typ výnimky, hodnotu výnimky a traceback, ak došlo k vyhodeniu výnimky.

          Pozrime sa na príklad:

          Klikni pre editáciu
          • import time
            
            class Timer:
                def __enter__(self):
                    self.start = time.time()
                    return self
            
                def __exit__(self, exc_type, exc_val, traceback):
                    self.end = time.time()
                    print(f"Duration: {self.end - self.start} seconds.")
            
            # Usage:
            with Timer() as t:
                # Code we want to measure:
                for i in range(1000000):
                    i *= 2
            # Upon exiting the 'with' block, the duration is printed
            • Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.

            Rozhodne nejde o kompletný zoznam všetkých dunder metód v daných kategóriách. To by jednak lekcia extrémne nadobudla na objeme a tiež by sa podobala skôr encyklopédii. Pre hlbšie štúdium je tu dokumentácia Pythona, kde je zoznam naozaj komplexný. To je pre túto lekciu všetko :-)

            V budúcej lekcii, Magické metódy v Pythone druhýkrát, sa pozrieme na ďalšie, pokročilejšie magické metódy objektov.


             

            Ako sa ti páči článok?
            Pred uložením hodnotenia, popíš prosím autorovi, čo je zleZnakov 0 z 50-500
            Predchádzajúci článok
            Vlastnosti v Pythone - Pokročilé vlastnosti a dedenie
            Všetky články v sekcii
            Objektovo orientované programovanie v Pythone
            Preskočiť článok
            (neodporúčame)
            Magické metódy v Pythone druhýkrát
            Článok pre vás napísal gcx11
            Avatar
            Užívateľské hodnotenie:
            16 hlasov
            (^_^)
            Aktivity