Preskoči na glavni sadržaj
Srednji Python2026-07-29 · 10 min čitanja

Objašnjenje dekoratora Pythona: od @property do logike ponovnog pokušaja u 15 minuta (2026.)

Dekorateri su značajka koja odvaja "zna Python" od "tečno čita Python". Izgledaju čarobno, ali su mehanički: @decorator na funkciji je točno f = decorator(f). To je to. Sve ostalo u ovom vodiču je ta jedna linija primijenjena u različitim oblicima.

Teorija jedne linije

Kad pišeš:

▶ PYTHONeditable · runs in your browser

Python ga pretvara u:

▶ PYTHONeditable · runs in your browser

To je cijela mehanika. @decorator_name iznad def pokreće def_name = decorator_name(def_name) nakon definicije. Ako ovo internalizirate, dekorateri zauvijek prestaju biti tajanstveni.

Pisanje vašeg prvog dekoratera (60 sekundi)

Dekorator je bilo koji poziv koji preuzima funkciju i vraća je. Tipičan oblik:

▶ PYTHONeditable · runs in your browser

*args, **kwargs u ovojnici obrambeni je uzorak — omogućuje dekorateru da radi na bilo kojoj funkciji bez obzira na potpis. Preskočite ga i dobit ćete "TypeError: wrapper() uzima 0 pozicijskih argumenata, ali su dana 2" u trenutku kada netko ukrasi funkciju parametrima.

Popravak @functools.wraps

Jedna suptilna greška: nakon ukrašavanja, add.__name__ je "wrapper", a ne "add". Dokumentacijski nizovi i tipski savjeti također nestaju. Popravak je jedan uvoz:

▶ PYTHONeditable · runs in your browser

Pravilo: svaki dekorater koji pišete treba koristiti `@functools.wraps(fn)`. Košta jedan redak i sprječava čitavu kategoriju problema s ispravljanjem pogrešaka (introspekcija, pytest fixtures, logging formatteri, pickle — svi se tiho kvare bez njega).

Četiri dekoratera koja ćete vidjeti u svakoj bazi koda

1. @property — izračunati atributi

▶ PYTHONeditable · runs in your browser

@property čini metodu pozivnom kao da je atribut. Savršeno za izvedene vrijednosti samo za čitanje. Postoji i @area.setter za stazu pisanja, ali 90% upotrebe @property je samo za čitanje.

2. @staticmethod i @classmethod

▶ PYTHONeditable · runs in your browser

@classmethod dobiva cls (samu klasu) i koristi se za alternativne konstruktore. @staticmethod ne dobiva ništa posebno i obična je funkcija koja slučajno živi unutar imenskog prostora klase.

3. @functools.cache — memoriranje

▶ PYTHONeditable · runs in your browser

Jedan od najmoćnijih stdlib dekoratora. Automatski memoizira funkciju na temelju njezinih argumenata. Zahtijeva da se svi argumenti mogu raspršiti (nema popisa / diktata kao argumenata — koristite torke).

4. @dataclasses.dataclass — eliminacija standardne ploče

▶ PYTHONeditable · runs in your browser

@dataclass čita bilješke tipa na razini klase i automatski generira __init__, __repr__, __eq__ i (s frozen=True) __hash__. To je najveće pojedinačno poboljšanje kvalitete života u Python 3.7+.

Pisanje dekoratera @retry (primjer iz stvarnog svijeta)

Dekorater koji ponovno pokušava funkciju u slučaju kvara s eksponencijalnim odmakom:

▶ PYTHONeditable · runs in your browser

Primijetite tri ugniježđene funkcije: retry prihvaća config argumente i vraća decorator; dekorator prihvaća funkciju i vraća omot; wrapper pokreće petlju ponovnog pokušaja. Ovaj troslojni uzorak je ono što svaki dekorater-s-argumentima izgleda - zapamtite oblik, a ne određeni primjer.

Dekorateri bazirani na klasi (rijetki, ali korisni)

Dekorater se može pozvati. Klase s __call__ također rade:

▶ PYTHONeditable · runs in your browser

Koristite kada dekorater treba zadržati stanje koje nadživljava jedan poziv (brojač, predmemorija, spremnik s ograničenjem brzine).

Uobičajene zamke

1. Zaboravljanje `@functools.wraps` — introspekcija se tiho prekida.

2. Promjenjivi zadani argumenti u samom dekoratoru — klasični def wrapper(x, cache=[]) grize greške i ovdje.

3. Ukrašavanje metoda bez prihvaćanja `self` — zapamtite self je samo pozicijski argument; *args, **kwargs dobro hvata.

4. Redoslijed je važan pri slaganju: @a\n@b\ndef f() je f = a(b(f)). Čitajte nizove odozdo prema gore.

Vježbajte

Napišite dekorater "@timing" koji ispisuje koliko je vremena potrebno da se obavi omotana funkcija, a zatim ga primijenite na funkciju koja izračunava "sum(range(10_000_000))". Cijeli dekorater sastoji se od 8 redaka s functools.wraps + time.perf_counter.


Jednom kada shvatite da je @x f = x(f), dekorateri postaju jedna od najproduktivnijih značajki Pythona. Posvuda su u stvarnim bazama koda: Flask/FastAPI rute (@app.route), pytest fixture (@pytest.fixture), Django prikazi (@login_required), Pydantic validatori (@field_validator). Ako ih sami naučite pisati, otključavate sposobnost čitanja svakog od njih.

Sljedeći korak: 10 praktičnih lekcija dekoratera — izgradite @retry, @memoise, @rate_limit i @requires_auth ispočetka sa pravim Pythonom koji radi u vašem pregledniku.

Jeste li spremni isprobati?

15 besplatne lekcije nakon besplatne prijave — bez kartice. Isprobajte platformu, a zatim odlučite.

Počni besplatno →

Or unlock every lesson

Pro — $12/mo, unlimited AI, cancel any time. Refund within 14 days worldwide.

See Pro plans →

Get one Python lesson + one career idea every Friday

No spam, no "buy our course now". Three bullets, every Friday. Unsubscribe with one click.