Decoratorii în Python

Funcțiile în Python sunt obiecte

Pentru a înțelege decoratorii, trebuie mai întâi să realizați că toate funcțiile din Python sunt obiecte. Aceasta implică o serie de consecințe. Să le examinăm pe un exemplu simplu:

Deci, amintiți-vă acest exemplu, vom reveni la ea. O altă caracteristică a funcțiilor în Python este că ele pot fi declarate în altă funcție!

Referințe privind funcțiile

Încă nu este confuz? Și acum cea mai interesantă parte. Deoarece funcțiile nu sunt altceva decât obiecte, rezultă:

  • ele pot fi atribuite variabilelor
  • ele pot fi declarate în interiorul unei alte funcții

Asta este, funcția poate reveni la o altă funcție ca rezultat:

Stop! Asta nu e tot! Dacă puteți returna o funcție, atunci puteți să o transmiteți și ca parametru.

Asta e tot și tot ce trebuie să știi despre decoratori. Adică decoratorii sunt ceva de genul unei cochilii. Acestea vă permit să executați codul înainte și după funcția pe care o înconjoară fără a schimba funcția însăși.

Decoratori de casa

Cum să le faci manual?

Acum, probabil veți face acest lucru pentru ca de fiecare dată când apelați a_stand_alone_function. în loc să funcționeze funcția a_stand_alone_function_decorated. Totul este destul de simplu, doar returnează funcția my_shiny_new_decorator de la a_stand_alone_function.

Expunerea decoratorilor

În exemplul anterior, se utilizează următoarea sintaxă de decorator:

Decoratorii este o versiune a Decoratorului de design pentru Python. În general, Python include mai multe modele clasice pentru a facilita procesul de dezvoltare, cum ar fi iteratorii.

Desigur, puteți acumula decoratori:

Utilizăm sintaxa de decoratori în Python:

Ordinea decoratorilor este:

În cele din urmă, răspunsul la întrebare

În concluzie, veți vedea răspunsul la întrebarea:

În principiu, acest lucru poate fi oprit, dar dacă dorința nu a fost încă pierdută pentru a afla mai multe despre decoratori, citiți mai departe.

Transmiterea parametrilor către funcțiile înconjurate de un decorator

Aplicarea decoratorilor la metode

După cum s-ar fi ghicit, în esență, metodele și funcțiile sunt aceleași în Python, cu excepția faptului că metodele trebuie să obțină o trimitere la obiectul părinte ca primul parametru (auto). Acest lucru înseamnă că decoratori pentru ei sunt construite exact în același mod. Doar nu uitați de sine:

Desigur, atunci când creați un decorator global, care va fi aplicat tuturor funcțiilor și metodelor, trebuie să utilizați * args și ** kwargs.

Parcurgerea parametrilor către decoratori

Excelent, dar ce spui despre transferul argumentelor către decorator? E un mic truc. De fapt, decoratorul are doar o funcție ca parametru și nu puteți să transmiteți argumente direct funcției înconjurate de decorator.

Înainte de a vă prezenta soluția, să examinăm un exemplu:

Nimic nu sa schimbat. Există un apel către deconectorul meu. Deci, când subliniați @my_decorator, spuneți că Python numesc funcția acestui decorator.

Nimic surprinzător. Faceți același lucru, dar săriți variabilele auxiliare:

Observat? Utilizăm un apel pentru funcții cu sintaxa @. Să ne întoarcem la decoratori cu argumente. Dacă folosim funcții pentru a genera decoratori în mișcare, atunci putem trece argumente la această funcție, nu-i așa?

Aici aveți un decorator cu argumente care pot fi setate folosind variabile.

După cum puteți vedea, orice decorator poate trece parametrii cu această abordare. Nimic nu împiedică utilizarea * args și ** kwargs. Dar amintiți-vă că decoratorii sunt chemați o singură dată. Numai atunci când Python importă acest script. Adică, nu puteți seta dinamic valorile acestor variabile. Când importați un script, funcția utilizează deja decoratorul, astfel încât să nu mai puteți schimba ceva mai târziu.

Un alt exemplu: decorator decorator decorator

Iată un astfel de bonus. Vă dau un fragment de cod, astfel încât orice decorator să accepte orice parametru. Ca rezultat, pentru a transfera argumentele, am creat decoratorul nostru cu ajutorul unei funcții auxiliare. Să scriem un decorator pentru decorator:

Un exemplu de utilizare:

Da, totul arata astfel: "Pentru a intelege recurenta, trebuie mai intai sa intelegeti recursiunea." Dar în cele din urmă nu simți că ai învățat ceva nou și interesant?

Aplicarea corectă a decoratorilor

  • Decorurile încetinesc funcțiile. Nu uita de asta.
  • Nu este posibilă îndepărtarea decoratorului din funcție. Desigur, există exemple despre cum să faceți acest lucru, dar nimeni nu o face. Deci, dacă ați aplicat decoratorul, va trebui să lucrați cu el în întregul cod.
  • Decoratorii înconjoară funcțiile, ceea ce face dificilă depanarea acestora.

Python 2.5 și mai sus reprezintă soluția la ultima problemă. Acesta include un modul functools (functools.wraps), care copiază numele, modulul și documentația fiecărei funcții zaddekorovannoy. Cel mai interesant lucru este functools.wraps și există un decorator.

Când trebuie folosite decoratoarele?

Întrebarea principală - și când, de fapt, se aplică decoratori? Desigur, ele arata grozav, dar unde sa le folosim? Pot cita cel puțin 1000 de exemple. Un exemplu clasic este adăugarea unei funcții pentru o funcție dintr-o bibliotecă terță parte (pe care nu o puteți edita). Puteți utiliza decoratorii pentru a extinde mai multe funcții, astfel încât să nu le suprascrieți de fiecare dată. Acest lucru elimină codul inutil:

Cel mai interesant este că puteți utiliza decoratorii aproape instantaneu, fără a suprascrie codul existent:

Articole similare