Mikuláš je tu! Získaj 90 % extra kreditov ZADARMO s promo kódom CERTIK90 pri nákupe od 1 199 kreditov. Len do nedele 7. 12. 2025! Zisti viac:
NOVINKA: Najžiadanejšie rekvalifikačné kurzy teraz s 50% zľavou + kurz AI ZADARMO. Nečakaj, táto ponuka dlho nevydrží! Zisti viac:

Diskusia – 17. diel - Dekorátory v Pythone

Späť

Upozorňujeme, že diskusie pod našimi online kurzami sú nemoderované a primárne slúžia na získavanie spätnej väzby pre budúce vylepšenie kurzov. Pre študentov našich rekvalifikačných kurzov ponúkame možnosť priameho kontaktu s lektormi a študijným referentom pre osobné konzultácie a podporu v rámci ich štúdia. Toto je exkluzívna služba, ktorá zaisťuje kvalitnú a cielenú pomoc v prípade akýchkoľvek otázok alebo projektov.

Komentáre
Posledné komentáre sú na spodnej časti poslednej stránky.
Avatar
Veronika Viková:21. apríla 10:59

Zatím jsem to dostatečně nepochopila, ale snad to do hlavy doběhne. Opět je použito něco, co nikde nebylo psáno, ale asi jsem to pochopila: cena_s_dani:.2f Kč - 2f tedy znamená dvě desetinná čísla?

Avatar
Petr Topinka
Člen
Avatar
Petr Topinka:23. apríla 19:45

Opět nevysvětlené funkce - .2f. Dále args a kwargs se dá vysvětlit i jinak jednodušeji, pochopitelně.(i bez znalosti tuple a slovníku) Kurz je časově dost nadupaný a odbornými výrazy se to ještě zamotává. kdybych nemel chatGPT, vůbec bych nepochopil, k čemu args a kwargs je

Avatar
Vanda Klepetková:25. apríla 14:19

def zapis_do_deni­ku(zprava):

nedostatečně a složitě vysvětleno, musela jsem si nechat pomoct od chatgpt

Avatar
Přemysl Tišer:12. júla 15:27

Chtělo by to podrobnější rozpracování, pomalejší postup. Velmi náročné na abstraktní myšlení funkcí měnit funkci funkce.

Avatar
Dalibor Šerfel:4. novembra 11:48

Zle vystvetlené, čitam to niekoľkokrát a aj tak tomu vôbec nerozumiem. A to args a kwargs, to je španielska dedina, nechápem ani ich funkciu, nie ich ešte zapísať do kódu. Haló, učím sa programovať 2 týždne a vysvetľujete to ako pre programátorov s 2 rokmi praxe.

Avatar
DarkCoder
Člen
Avatar
Odpovedá na Dalibor Šerfel
DarkCoder:4. novembra 13:45

Dekorátor je funkce, která jako argument přijímá jinou funkci a vrací novou funkci.

primitivní příklad:

def pozdrav_dekorator(funkce):
    def obal():
        print("Ahoj!")
        funkce()
        print("Měj se!")
    return obal

@pozdrav_dekorator
def moje_funkce():
    print("Já jsem funkce uvnitř.")

moje_funkce()

Dekorátor pozdrav_dekorator obalí funkci moje_funkce.
Když se zavolá moje_funkce(), ve skutečnosti se spustí obal(), který modifikuje chování původní funkce. V našem případě přidá pozdrav a rozloučení.

Pokud má dekorovaná funkce parametry, musí to dekorátor umět zpracovat — jinak by došlo k chybě při volání. Řeší se to pomocí konstrukce *args a **kwargs, které zachytí libovolný počet pozičních a pojmenovaných argumentů.

def pozdrav_dekorator(funkce):
    def obal(*args, **kwargs):
        print("Ahoj!")
        vysledek = funkce(*args, **kwargs)
        print("Měj se!")
        return vysledek
    return obal

@pozdrav_dekorator
def secti(a, b):
    print(f"Sčítám {a} + {b}")
    return a + b

vysledek = secti(3, 5)
print("Výsledek:", vysledek)

Kdy použít *args a **kwargs

Používáš je vždy, když nevíš předem, kolik argumentů funkce může mít nebo když chceš, aby dekorátor fungoval pro libovolnou funkci (s různým počtem a typem parametrů).

*args zachytí všechny poziční argumenty jako n-tici
**kwargs zachytí všechny pojmenované argumenty jako slovník

Kdy je nepotřebuješ

Pokud přesně víš, že tvoje dekorovaná funkce bude mít konkrétní parametry, můžeš je uvést přímo:

def pozdrav_dekorator(funkce):
    def obal(a, b):
        print("Ahoj!")
        vysledek = funkce(a, b)
        print("Měj se!")
        return vysledek
    return obal

@pozdrav_dekorator
def secti(a, b):
    return a + b

Tohle bude fungovat jen pro funkce se dvěma argumenty (a, b).

Kdy je lepší dělat obecný dekorátor

Použiješ *args a **kwargs, když:

  • chceš, aby fungoval pro libovolnou funkci, bez ohledu na počet nebo typ parametrů,
  • plánuješ ho znovupoužívat na více místech v kódu,
  • nevíš dopředu, jak bude vypadat funkce, kterou bude dekorovat.
import time

def mer_cas(funkce):
    def obal(*args, **kwargs):
        start = time.time()
        vysledek = funkce(*args, **kwargs)
        konec = time.time()
        print(f"Trvalo to {konec - start:.4f} s")
        return vysledek
    return obal

@mer_cas
def vypocet(n):
    return sum(range(n))

vypocet(1_000_000)

Tento dekorátor bude fungovat na libovolnou funkci, ať už má jeden argument, nebo deset.

Kdy je lepší dělat specializovaný dekorátor

Bez *args, **kwargs, když:

  • víš přesně, jaké parametry bude funkce mít,
  • chceš mít jednodušší a čitelnější kód,
  • dekorátor potřebuje konkrétně pracovat s argumenty (např. validovat hodnotu a nebo b).

Specializovaný tedy použiješ tam když: víš přesně, co dekoruješ jednodušší, přehledný, ale nelze znovu použít jinde.
Obecný (*args, **kwargs) použiješ tam kde chceš aby byl pro více funkcí univerzální, flexibilní kód ale bývá trochu složitější.

V praxi se skoro vždy používá obecný dekorátor, protože je univerzální.

Univerzální definice dekorátoru

def dekorator(funkce):
    def obal(*args, **kwargs):
        # --- Kód před voláním původní funkce ---
        print("Něco se děje před voláním funkce...")

        # Zavolání původní funkce s libovolnými argumenty
        vysledek = funkce(*args, **kwargs)

        # --- Kód po volání původní funkce ---
        print("Něco se děje po volání funkce...")

        # Vrácení výsledku původní funkce
        return vysledek

    return obal

A použití:

@dekorator
def moje_funkce(a, b, pozdrav="ahoj"):
    print(f"{pozdrav}, sčítám {a} + {b}")
    return a + b

vysledek = moje_funkce(3, 4, pozdrav="čau")
print("Výsledek:", vysledek)

Co je důležité si zapamatovat

  • dekorator je funkce, která přijímá funkci a vrací funkci.
  • *args a **kwargs zajišťují, že dekorátor bude fungovat pro libovolný počet a typ argumentů.
  • Vnitřní funkce obal() je ta, která se reálně spouští místo původní.

Snad Ti tohle více pomohlo.

Odpovedať
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Odpovedá na DarkCoder
Dalibor Šerfel:5. novembra 9:47

Dík, už tomu chápem trochu lepšie

Avatar
DarkCoder
Člen
Avatar
Odpovedá na Dalibor Šerfel
DarkCoder:5. novembra 9:55

Není zač. Pokud s programováním začínáš, můžeš dekorátory s klidem letmo prolétnout. Jsou mnohem důležitější konstrukce které potřebuješ znát než tohle.

Odpovedať
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
DarkCoder:5. novembra 11:07

Pro všechny co chtějí pochopit vícenásobné dekorování:

Základní princip

Pokud máme na funkci více dekorátorů, aplikují se odspodu nahoru, tedy nejblíže funkci jako první.

Máme-li:

@A
@B
@C
def f():
    pass

tak to odpovídá:

def f():
    pass
f = C(f)
f = B(f)
f = A(f)

Dekorátor C je nejblíže funkci, takže se zavolá jako první a vrátí „zabalenu“ funkci. Pak se tato „zabalená“ funkce předá do B, který ji dále obalí. Nakonec A obalí celý výsledek.

Příklad:

def deco1(func):
    def wrapper():
        print("deco1 před voláním")
        func()
        print("deco1 po volání")
    return wrapper

def deco2(func):
    def wrapper():
        print("deco2 před voláním")
        func()
        print("deco2 po volání")
    return wrapper

@deco1
@deco2
def hello():
    print("Ahoj!")

hello()

Výsledek:

deco1 před voláním
deco2 před voláním
Ahoj!
deco2 po volání
deco1 po volání

Tedy:
Pořadí obalování - Odspodu nahoru
Pořadí volání při běhu - Zvenku dovnitř

Shrnutí:
Fáze Pořadí dekorátorů Co se děje
Aplikace (definice) C → B → A f = A(B(C(f)))
Volání při běhu A → B → C A zavolá B, ten C, ten f

blíží se Vánoce tak drobná analogie:

Představ si, že balíš dárek do tří vrstev papíru:

Nejprve ho zabalíš do C (nejblíže obsahu),
pak do B,
nakonec do A.

Když pak dárek rozbaluješ (voláš funkci),
nejdřív musíš sundat A, pak B, a nakonec C, než se dostaneš k samotné funkci.

Odpovedať
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Posledné komentáre sú na spodnej časti poslednej stránky.
Robíme čo je v našich silách, aby bola tunajšia diskusia čo najkvalitnejšia. Preto do nej tiež môžu prispievať len registrovaní členovia. Pre zapojenie sa do diskusie sa zaloguj. Ak ešte nemáš účet, zaregistruj sa, je to zadarmo.

Zobrazené 9 správy z 29.