Objektové programovanie v Pythone

Objekt

Množina dát (atribútov) a množina funkcií (metód ktoré pracujú s tými dátami).

V Pythone je všetko objekt.

📚 Oficiálna dokumentácia: Python Data Model · 📖 Dive Into Python 3: Native Datatypes

Reťazce sú objekty

Metódy urobia niečo s objektom a vrátia nový objekt.

pozdrav = "Dobré ráno"
# máme metódy pre prácu s reťazcami
pozdrav.upper()  # "DOBRÉ RÁNO"
pozdrav.lower()  # "dobré ráno"
pozdrav.replace("ráno", "populudnie")  # "Dobré populudnie"

📚 Oficiálna dokumentácia: textové sekvencie · 📖 Dive Into Python 3: Strings

Mutable a inputable objekty

  • Mutable objekty sa dajú meniť, inputable nie.
  • Mutable objekty: list, dict, set
  • Inputable objekty: int, float, str, tuple

📚 Oficiálna dokumentácia: built-in types · 📖 Dive Into Python 3: Native Datatypes

Životný cyklus objektu

  1. Vytvorenie objektu
pozdrav = "Dobré ráno"
  1. Použitie objektu
print(pozdrav.upper())
  1. Zničenie objektu
del pozdrav

Explicitné zničenie objektu je nepovinné, Python sa o to stará sám.

📚 Oficiálna dokumentácia: objects, values and types · 📖 Dive Into Python 3: Native Datatypes

Referencie na objekt

Na jeden objekt je môže existovať viacero referencií.

pozdrav1 = "Dobré ráno"
pozdrav2 = pozdrav1  # obe referencie ukazujú na rovnaký objekt

📚 Oficiálna dokumentácia: assignment statements · 📖 Dive Into Python 3: Native Datatypes

Kopírovanie objektov

Priradenie v Pythone neznamená kopírovanie objektu, ale vytvorenie novej referencie na existujúci objekt.

Ak cheme vytvoriť nový objekt s rovnakou hodnotou, musíme použiť kopírovanie.

Kopírovanie zoznamu pomocou konštruktora list():

list1 = [1, 2, 3]
list2 = list(list1)  # vytvorí nový objekt
list1.append(4)
print(list1)  # [1, 2, 3, 4]
print(list2)  # [1, 2, 3]

Toto je tzv. "shallow copy" (plytké kopírovanie) - vytvorí nový zoznam, ale jeho prvky sú stále referencie na pôvodné objekty.

📚 Oficiálna dokumentácia: copying · 📖 Dive Into Python 3: Native Datatypes

Garbage collector

mechanizmus, ktorý sa stará o uvoľňovanie pamäte.

V Pythone sa objekty z pamäte uvoľňujú automaticky, keď na ne už neexistuje žiadna referencia.

Čas automatického uvoľňovania pamäte je riadený garbage collectorom a nie je predvídateľný.

Ako často sa spúšťa garbage collector závisí od implementácie Pythona a od toho, ako je program napísaný.

📚 Oficiálna dokumentácia: gc — garbage collector

Vytváranie vlastných tried

Definujeme:

  • Atribúty
  • Metódy
  • spôsob inicializácie (konštruktor)
  • spôsob uvoľňovania zdrojov (deštruktor)

📚 Oficiálna dokumentácia: classes · 📖 Dive Into Python 3: Classes & Iterators

Trieda je šablóna pre vytvorenie objektov

class Dog:
    def __init__(self, name):
        self.name = name

dog1 = Dog("Buddy")

trieda = údajový typ = spôsob uloženia v pamäti

📚 Oficiálna dokumentácia: class definitions · 📖 Dive Into Python 3: Classes & Iterators

Atribúty a metódy

  • Atribúty: premenné v triede
  • Metódy: funkcie v triede
  • self je smerník na aktuálny objekt
class Dog:
    def __init__(self, name):
        # self.name je atribút
        self.name = name

    # self.bark() je metóda
    def bark(self):
        return "Haf!"

📚 Oficiálna dokumentácia: class instances · 📖 Dive Into Python 3: Classes & Iterators

Atribúty

Každý objekt je inštancia triedy.

inštancia = trieda s konkrétnymi hodnotami atributov.

class Counter:
    step  = 0  # triedna premenná
    def __init__(self):
        self.count = 0

    def increment(self):
        self.count += Counter.step

📚 Oficiálna dokumentácia: class and instance variables · 📖 Dive Into Python 3: Classes & Iterators

Metódy

Opisujú správanie objektu

menia hodnoty atribútov a spôsobujú vedľajšie efekty

📚 Oficiálna dokumentácia: method objects · 📖 Dive Into Python 3: Classes & Iterators

Konštruktor a deštruktor

Konštruktor je špeciálna metóda, ktorá sa volá na začiaktku a nastavuje počiatočné hodnoty atribútov.

Alokuje zdroje.

Deštruktor sa stará o uvoľnenie zrojov.

  • __init__ → inicializácia objektu
  • __del__ → čistenie (zriedka používané)

📚 Oficiálna dokumentácia: object initialization and finalization · 📖 Dive Into Python 3: Classes & Iterators

class Person:
    def __init__(self, name):
        self.name = name

    # deštruktor väčšinou v Pythone nie je potrebný
    def __del__(self):
        print("Objekt zmazaný")

Špeciálne metódy

  • Špeciálne metódy s __
  • Umožňujú preťaženie operátorov
class Vector:
    def __init__(self, x):
        self.x = x

    def __add__(self, other):
        return Vector(self.x + other.x)

📚 Oficiálna dokumentácia: special method names · 📖 Dive Into Python 3: Special Method Names

Pri vytváraní novej triedy vieme využiť existujúce triedy (dedičnosť) a rozšíriť ich o nové atribúty a metódy.

Inheritance vs Composition

  • Dedičnosť (Inheritance) – vytvárame novú triedu na základe existujúcej triedy. Nová trieda dedí atribúty a metódy z rodičovskej triedy a môže ich rozšíriť alebo prepísať.
  • Kompozícia (Composition) – vytvárame novú triedu, ktorá obsahuje iné objekty ako svoje atribúty. Nová trieda využíva funkcionalitu týchto objektov a môže ich kombinovať alebo rozširovať.

📚 Oficiálna dokumentácia: inheritance · 📖 Dive Into Python 3: Classes & Iterators

Príklad dedičnosti:

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Haf!"

📚 Oficiálna dokumentácia: inheritance · 📖 Dive Into Python 3: Classes & Iterators

Príklad kompozície:

class Engine:
    def start(self):
        print("Motor sa spustil.")

class Car:
    def __init__(self):
        self.engine = Engine()

    def start(self):
        self.engine.start()

📚 Oficiálna dokumentácia: class objects · 📖 Dive Into Python 3: Classes & Iterators

Polymorfizmus

  • Python je slabodynamický typovací jazyk, čo znamená, že typy objektov sa určujú až za behu programu.
  • Funkcia môže prijímať argumenty rôznych typov a správať sa odlišne v závislosti od typu argumentu.
  • Polymorfizmus je schopnosť objektov rôznych typov reagovať na rovnakú metódu alebo operáciu. V Pythone sa polymorfizmus dosahuje prostredníctvom dedičnosti a Duck Typing.

📚 Oficiálna dokumentácia: glossary — polymorphism · 📖 Dive Into Python 3: Classes & Iterators

Rozhrania v Pythone - Duck Typing

  • Duck Typing je koncept, ktorý umožňuje používať objekty rôznych typov, pokiaľ majú rovnaké metódy alebo atribúty. V Pythone sa nevyžaduje explicitné deklarovanie rozhraní, stačí, aby objekt implementoval požadované metódy.
  • Príklad Duck Typing:
class Bird:
    def fly(self):
        print("Vták lieta.")

class Airplane:
    def fly(self):
        print("Lietadlo lieta.")

def make_it_fly(thing):
    thing.fly()

📚 Oficiálna dokumentácia: glossary — duck typing

Výnimky (Exceptions)

Funkcia sa môže skončiť neočakávaným spôsobom:

  • súbor sa nenašiel
  • spojenie sa nepodarilo
  • Operácia trvá príliš dlho
  • nie je dosť zdrojov.

📚 Oficiálna dokumentácia: errors and exceptions · 📖 Dive Into Python 3: Exceptions

Výnimka je spôsob hlásenia chyby pri vykonávaní funkcie ktorý obchádza návratovú hodnotu.

Fukcia s výnimkami má potom dva rôzne spôsoby ukončenia:

  • návratová hodnota.
  • výnimka, návratová hodnmota nie je k dispozícii.
  • Bezpečné spracovanie chýb počas behu programu
try:
    x = int("abc")
except ValueError:
    print("Konverzia zlyhala")

Čo sú výnimky?

  • Výnimka (exception) je nečakaná udalosť, ktorá nastane za behu programu.
  • Ak ju nevyriešime, program zlyhá s chybou.
  • Príklady:
    • delenie nulou
    • neexistujúci súbor
    • nesprávny vstup od používateľa

Ako sa výnimky spracúvajú?

  • Používame blok try – skús
  • Nasleduje blok except – chytaj
  • Ak nastane chyba, skript neskončí – reagujeme podľa typu chyby

Základný tvar: try / except

try:
    vysledok = 10 / 0
except ZeroDivisionError:
    print("Chyba: delenie nulou!")

Výstup:

Chyba: delenie nulou!

Bez except by program zlyhal.

📚 Oficiálna dokumentácia: handling exceptions · 📖 Dive Into Python 3: Exceptions

Chytanie viacerých chýb

try:
    x = int(input("Zadaj číslo: "))
    print(10 / x)
except ValueError:
    print("Chyba: zadali ste niečo iné ako číslo.")
except ZeroDivisionError:
    print("Chyba: nedelíš nulou!")

Chytanie viacerých chýb naraz

try:
    x = int(input("Zadaj číslo: "))
    print(10 / x)
except (ValueError, ZeroDivisionError):
    print("Chyba: nesprávny vstup.")

Zachytenie objektu výnimky

try:
    x = int(input("Zadaj číslo: "))
    print(10 / x)
except ValueError as e:
    print(f"Chyba: {e}")
except ZeroDivisionError as e:
    print(f"Chyba: {e}")

Všeobecný except

try:
    x = int(input("Zadaj číslo: "))
    print(10 / x)
except Exception as e:
    print(f"Nečakána chyba: {e}")

👉 Využíva sa ako záložná možnosť. 👉 Neodporúča sa chytall Exception bez potreby — môže zakryť iné chyby.

Blok finally

try:
    f = open("data.txt")
    data = f.read()
except FileNotFoundError:
    print("Súbor nebol nájdený.")
finally:
    print("Ukončenie operácie.")

Blok finally sa vykoná vždy — či už nastala chyba, alebo nie. Používa sa na upratovanie (zatvorenie súboru, spojenia, ...).

Úplný tvar

try:
    # kód, ktorý môže zlyhať
    vysledok = 10 / x
except ZeroDivisionError:
    # ak nastane konkrétna chyba
    print("Delenie nulou!")
else:
    # ak nič nezlyhalo
    print(f"Výsledok: {vysledok}")
finally:
    # toto sa vykoná vždy
    print("Hotovo.")

Poradie: tryexceptelsefinally

📚 Oficiálna dokumentácia: try statement · 📖 Dive Into Python 3: Exceptions

raise – vyvolanie výnimky

vek = int(input("Zadaj vek: "))

if vek < 0:
    raise ValueError("Vek nemôže byť záporný.")

print(f"Máš {vek} rokov.")

Výstup pri zápornom veku:

Traceback (most recent call last):
  ...
ValueError: Vek nemôže byť záporný.

📚 Oficiálna dokumentácia: raise · 📖 Dive Into Python 3: Exceptions

Kedy použiť raise?

  • Ak je vstup neplatný alebo stav nedetekovateľný inak.
  • Ak chceme explicitne hlásiť chybu vo funkcii.
def nastav_vek(vek):
    if vek < 0:
        raise ValueError("Vek musí byť nezáporné číslo.")

Vlastné výnimky

class NedostatokPenezError(Exception):
    pass

def plat(suma):
    if suma > 100:
        raise NedostatokPenezError("Nedostatok prostriedkov.")

Použitie:

try:
    plat(150)
except NedostatokPenezError as e:
    print(e)

📚 Oficiálna dokumentácia: user-defined exceptions · 📖 Dive Into Python 3: Exceptions

Hierarchia vlastných výnimiek

class AppError(Exception):
    pass

class NedostatokPenezError(AppError):
    pass

class ChybaAutentifikacie(AppError):
    pass

Chytíme všetky chyby aplikácie:

try:
    ...
except AppError as e:
    print(f"Aplikačná chyba: {e}")

📚 Oficiálna dokumentácia: built-in exceptions · 📖 Dive Into Python 3: Exceptions

Literatúra

Dive Into Python 3, časť o výnimkách

Zdroje na prečítanie

  • Oficiálna dokumentácia — Exceptions: https://docs.python.org/3/tutorial/errors.html
  • Exception Hierarchy: https://docs.python.org/3/library/exceptions.html
  • Built-in Exceptions: https://docs.python.org/3/library/exceptions.html#built-in-exceptions

    Vo výnimke je uložená informácia o vzniknutom stave - chybové hlásenie

Podľa vzniknutej situácie vieme:

  • zaznamenať alebo hlásiť správu o chybe
  • Ukončiť program
  • ignorovať situáciu
  • pokúsiť sa korigovať chybu a pokračovať

Vyhadzovanie výnimiek

def divide(a, b):
    if b == 0:
        raise ValueError("Delenie nulou nie je povolené")
    return a / b

Chytanie výnimiek.

Výnimky sú organmizované do tried.

Chytíme určitú triedu výnimiek.

Vieme zachytiť aj konkrétny objekt s výnmimkou.

Pri ošetrení výnimky sa zameriame na uričý druh výnimky.

Iterátory

  • Zložitejší spôsob zápisu generátorov

  • Objekty, chojúce sa ako zoznamy, ale neukladajú všetky prvky v pamäti

  • Implementujú rozhranie:

    • __iter__()
    • __next__() vyhadzuje výnimku StopIteration, keď sa prvky minú

📚 Oficiálna dokumentácia: iterator protocol · 📖 Dive Into Python 3: Classes & Iterators

class Counter:
    def __init__(self, max):
        self.max = max
        self.current = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.current < self.max:
            self.current += 1
            return self.current
    else:
        raise StopIteration

📚 Oficiálna dokumentácia: __iter__() and __next__() · 📖 Dive Into Python 3: Classes & Iterators

priklad ako použiť iterátor

counter = Counter(5)
for num in counter:
    print(num)

📚 Oficiálna dokumentácia: iter() and next() · 📖 Dive Into Python 3: Classes & Iterators

Aj trieda je objekt

  • Introspekcia

📚 Oficiálna dokumentácia: classes as objects · 📖 Dive Into Python 3: Classes & Iterators

Literatúra

Dive Into Python 3, druhá polovica

Reload?