Decoratorii Python de la început până la sfârșit

Python: Funcționează ca obiecte

Pentru a înțelege ce decoratori sunt, mai întâi trebuie să înțelegeți că funcțiile din Python sunt obiecte. Această înțelegere este foarte importantă. Să examinăm într-un exemplu simplu:








Păstrați această informație în mintea voastră, vom reveni în curând la ea. O altă proprietate interesantă a funcțiilor în Python este că ele pot fi definite ... într-o altă funcție!

Referință referință

Bine, încă mai ești aici? Acum începe partea veselă. Ați văzut deja că aceste funcții sunt obiecte și prin urmare acestea sunt:
-Poate fi atribuită unei variabile;
-Poate fi definit în cadrul altor funcții.

Ca rezultat, acest lucru înseamnă că funcția poate returna alte funcții :-) [probabil dublu sens aici „return“: 1) ca un operator „poate provoca o declarație de returnare pentru funcțiile“ și acțiunea „să se întoarcă“. Înțelesul nu se schimba absolut nimic, doar am crezut că a fost amuzant :-) aprox. traducător]
Să vedem:

Dar așteaptă, nu e tot! Dacă puteți reveni la o funcție, puteți să o utilizați ca opțiune:

Excelent! Acum știi tot ce ai nevoie pentru a înțelege decoratorii. Decoratorii sunt împachetatori, ceea ce înseamnă,
că vă permit să executați codul înainte și după apelarea funcției pe care o înfășoară fără a fi nevoie să schimbați funcția în sine.

Decoratori cu mâinile lor

Cum de a scrie un decorator:

Acum, poate doriți să apelați de fiecare dată când a_stand_alone_function, funcția a_stand_alone_function_decorated în schimb a fost cauzat.
Este foarte ușor! Doar reassign a_stand_alone_function la funcția returnată de my_shiny_new_decorator:

Descoperim secretul decoratorilor!

Exemplul anterior, folosind sintaxa decoratorilor:

Da, e chiar mei. Decoratorul este doar o scurtă formă de scriere:

Decoratorii sunt doar o varianta Python a modelului de design decorator. În general, pentru o dezvoltare simplă în Python, mai multe modele de design clasic sunt construite, de exemplu, în iteratori.

Desigur, puteți conecta decoratorii între ele:

Același lucru, folosind sintaxa de decoratori în Python:

Ordinea în care aranjați decoratorii are o valoare:

[deoarece aceasta este o traducere a răspunsului din stackoverflow, a existat un răspuns la întrebare, nu aduce nimic nou și cade din context, așa că am decis să îl eliminăm]

Acum, puteți să mergeți departe fericit sau mai mult din creierul dvs. și să învețe cum să utilizați decoratori la un nivel mai avansat!

Trecerea argumentelor la funcția de decorator

Metode de "decorare"

Ce este cu adevărat cool despre Python este că metodele și funcțiile sunt de fapt aceleași, cu o diferență,
că metoda se așteaptă ca primul parametru care se referă la un anumit obiect (auto).






Asta inseamna ca poti face decoratorul metodei in acelasi mod ca si functia, tine cont doar de faptul ca este necesar sa treci singur:

Desigur, dacă faci un decorator foarte versatil și doresc ca el va lucra cu orice funcție sau metodă, indiferent de argumentele lor, apoi utilizați doar arg *, ** kwargs:

Trecem argumente către decorator

Excelent! Dar ce spui despre transferarea argumentelor către decorator? Desigur, va trebui să ne întoarcem puțin, deoarece decoratorul trebuie să accepte funcția ca argument și din acest motiv nu puteți trece argumentele funcției decorate direct la decorator.
Înainte de a încerca să rezolv o problemă, să scriem un memento mic:

De fapt - este același lucru. Pur și simplu numește "my_decorator". Deci, când scrieți @my_decorator, îi spuneți lui Python să apeleze o funcție definită de variabila "my_decorator". Acest lucru este foarte important, deoarece eticheta [variabilă nume] poate îndrepta direct spre decorator ... sau nu! Să mergem în rău!

Nu există surprize aici. Să facem exact același lucru, dar să sărim peste variabilele intermediare:

Să o facem din nou, chiar și mai scurtă:

Hei, ai văzut asta? Am folosit funcția de apel cu sintaxa "@" :-)

Să ne întoarcem la decoratori cu argumentele. Dacă putem folosi funcția pentru a genera decoratorul în zbor, putem trece argumente la această funcție, nu?

Aici este, decoratorul cu argumente. Argumentele pot fi atribuite variabilelor:

După cum puteți vedea, puteți transmite argumente către decorator ca orice altă funcție care utilizează acest truc. De asemenea, puteți utiliza * args, ** kwargs dacă doriți. Dar amintiți-vă, decoratorii sunt chemați o singură dată. Apoi, când Python importă scriptul. Nu puteți aloca dinamic argumente după aceasta. Când executați "import x", funcția este deja decorată, deci nu puteți schimba nimic.

O mică practică: decorator, pentru decorarea decoratorilor.

Și ca un bonus, vă dau un snip pentru a crea orice decorator care acceptă orice variabilă. În final, pentru a accepta argumentele, am creat un decorator care folosește funcția. Am înfășurat decoratorul. Tot ce am văzut recent, doar o funcție înfășurată? Aaa, decoratori! Hai sa ne distram si sa scriem un decorator pentru decorator:

Putem folosi acest cod după cum urmează:

Cred că ultima dată când ați simțit același sentiment ca după fraza "Înainte să înțelegeți recursiunea, trebuie să înțelegeți recursiunea". Dar, pe de altă parte, te-ai simțit mulțumit de stăpânirea acestui lucru?

Cele mai bune practici pentru utilizarea decoratorilor

- Au fost adăugate în Python 2.4, deci asigurați-vă că codul dvs. rulează.
- Decoratorii încetinesc apelul pentru funcții. Ține minte asta
- Nu puteți "anula" funcția. Există hack-uri care ar crea decoratori care pot fi îndepărtați, dar nimeni nu le folosește. Deci, odată ce funcția este reluată, este pentru totdeauna. De-a lungul codului.
- Decoratorii împletesc funcțiile care le pot complica depanarea.
Python 2.5 rezolvă acest din urmă problema prin furnizarea unui functools module, inclusiv functools.wraps care copiază numele modulului și orice șir de documentație „învelit“ funcție în ambalajul. Funny fact, functools.wraps - decorator :-)

Cum pot fi folosiți decoratorii?

În cele din urmă, întrebarea principală: de ce pot folosi decoratorii? Arată grozav și puternic, dar ar fi minunat să vedem un exemplu practic. Există 1000 de posibilități. Utilizarea clasică este o extensie a comportamentului funcției de la o bibliotecă externă (o puteți modifica) sau pentru depanare (nu doriți să o modificați deoarece este temporară). Puteți folosi decoratorii pentru a extinde mai multe funcții cu același cod, fără a le suprascrie de fiecare dată din nou, de dragul principiului DRY. De exemplu:

Și, bineînțeles, este minunat să puteți folosi decoratori pentru orice și oricând fără a rescrie. DRY în acțiune:







Articole similare

Trimiteți-le prietenilor: