MC, 2025
Ilustracja do artykułu: Nepričakovana Moč Dekoratorjev v Pythonu: Razloženo!

Nepričakovana Moč Dekoratorjev v Pythonu: Razloženo!

Python je znan po svoji preprostosti in eleganci, vendar za tiste, ki se podajajo globlje v jezik, dekoratorji pogosto predstavljajo prvo resno uganko. Toda brez skrbi! Če ste se kdaj spraševali, kaj pomeni @ v Pythonu ali zakaj bi sploh uporabljali dekoratorje – ste na pravem mestu. V tem članku bomo razložili koncept “python decorators explained” na jasen, pozitiven in igriv način, podkrepili s primeri in vas opremili z znanjem, ki ga boste z veseljem uporabili.

Kaj so dekoratorji v Pythonu?

Preprosto povedano, dekoratorji v Pythonu so funkcije, ki sprejmejo drugo funkcijo kot argument in vrnejo novo funkcijo, ki običajno razširi vedenje izvirne funkcije – brez da bi jo morali neposredno spreminjati. To pomeni, da lahko funkcionalnosti dodajate dinamično.

Najpogostejši primer, kjer vidimo dekoratorje, je pri uporabi @ nad funkcijo. Na primer:

def moj_dekorator(func):
    def ovijac():
        print("Nekaj se dogaja pred funkcijo...")
        func()
        print("Nekaj se dogaja po funkciji...")
    return ovijac

@moj_dekorator
def pozdrav():
    print("Pozdravljen, svet!")

pozdrav()

Rezultat zgoraj bo:

Nekaj se dogaja pred funkcijo...
Pozdravljen, svet!
Nekaj se dogaja po funkciji...

Zakaj uporabljati dekoratorje?

Uporaba dekoratorjev omogoča:

  • Ločevanje skrbi (separation of concerns)
  • Čistejšo in bolj modularno kodo
  • Ponovno uporabo logike, kot je beleženje, preverjanje pravic, merjenje časa

Namesto da dodajamo isto funkcionalnost vsakemu kosu kode, jo lahko "zavijemo" v dekorator.

Primer: Merjenje časa izvajanja funkcije

Primer dekoratorja, ki meri čas, ki ga funkcija potrebuje za izvajanje:

import time

def meri_cas(func):
    def ovijac(*args, **kwargs):
        zacetek = time.time()
        rezultat = func(*args, **kwargs)
        konec = time.time()
        print(f"Funkcija {func.__name__} je trajala {konec - zacetek:.4f} sekund")
        return rezultat
    return ovijac

@meri_cas
def pocasi():
    time.sleep(2)
    print("Konec spanja.")

pocasi()

Python decorators explained s praktičnimi primeri

Za še boljšo ponazoritev, tukaj je več primerov, ki prikazujejo, kako uporabiti dekoratorje za preverjanje pravic, beleženje in spreminjanje izhodov funkcij.

Primer: Preverjanje pravic uporabnika

def preveri_dostop(func):
    def ovijac(*args, **kwargs):
        uporabnik = kwargs.get('uporabnik', '')
        if uporabnik != 'admin':
            print("Dostop zavrnjen!")
            return
        return func(*args, **kwargs)
    return ovijac

@preveri_dostop
def izbrisi_podatke(uporabnik=''):
    print("Podatki izbrisani.")

izbrisi_podatke(uporabnik='gost')  # Dostop zavrnjen!
izbrisi_podatke(uporabnik='admin')  # Podatki izbrisani.

Verižni dekoratorji

V Pythonu lahko uporabimo več dekoratorjev hkrati – to pomeni, da lahko funkcijo večkrat ovijemo, vsak z različnim vedenjem:

def prvi(func):
    def ovijac():
        print("Prvi")
        return func()
    return ovijac

def drugi(func):
    def ovijac():
        print("Drugi")
        return func()
    return ovijac

@prvi
@drugi
def test():
    print("Izvorna funkcija")

test()

Rezultat bo:

Prvi
Drugi
Izvorna funkcija

Argumenti funkcij in dekoratorji

Če želimo, da naš dekorator deluje s funkcijami, ki sprejemajo argumente, uporabimo *args in **kwargs, kot smo že pokazali zgoraj. To omogoča, da dekorator sprejme poljubno število pozicijskih in poimenovanih argumentov.

Napredni: Dekoratorji z argumenti

Včasih želimo, da naš dekorator sam sprejme argumente. V takem primeru uporabimo funkcijo, ki vrne dekorator:

def pozdravi_z(ime):
    def dekorator(func):
        def ovijac(*args, **kwargs):
            print(f"Pozdrav od {ime}!")
            return func(*args, **kwargs)
        return ovijac
    return dekorator

@pozdravi_z("Maja")
def testna_funkcija():
    print("To je test.")

testna_funkcija()

Kaj pa functools.wraps?

Ko uporabljamo dekoratorje, funkcija izgubi svoje metapodatke – kot je njeno ime ali dokumentacija. Da to popravimo, uporabimo functools.wraps:

from functools import wraps

def logiraj(func):
    @wraps(func)
    def ovijac(*args, **kwargs):
        print(f"Klic funkcije: {func.__name__}")
        return func(*args, **kwargs)
    return ovijac

@logiraj
def neka_funkcija():
    """To je testna funkcija."""
    print("Delam nekaj...")

print(neka_funkcija.__name__)  # zdaj vrne 'neka_funkcija'
print(neka_funkcija.__doc__)   # vrne 'To je testna funkcija.'

Sklepne misli: python decorators explained

Upamo, da je bil naš članek “python decorators explained” uporaben in zanimiv. Dekoratorji so izjemno močno orodje v Pythonu, in čeprav so sprva morda nekoliko zagonetni, se njihova moč pokaže v resnični uporabi – naj bo to pri beleženju, preverjanju, ali celo razširitvi funkcionalnosti brez podvajanja kode.

Ne bojte se eksperimentirati, igrati z lastnimi dekoratorji in jih uporabiti tam, kjer bi sicer morali kopirati podobno kodo večkrat. To je prava lepota Pythonove fleksibilnosti!

Komentarze (0) - Nikt jeszcze nie komentował - bądź pierwszy!

Imię:
Treść: