Python dekoratérov - je to, čo?

Decorator je šablóna navrhnutá na pripojenie ďalšieho správania k objektu. Používa sa v mnohých jazykoch OOP: Java, C #, PHP, JS. Python nie je výnimkou. Úlohu dekoratérov je možné opísať v nasledujúcom príklade. Existuje objekt, ktorý vykonáva nejakú funkciu, počas vývoja programu, ktorý potrebujete k jeho pridanie. Môže sa vykonávať pred alebo po, alebo dokonca počas hlavných funkcií. Dekorátory sa používajú na vyriešenie tohto problému. Rozširujú funkčnosť a eliminujú vytvorenie druhej kategórie s ďalšími metódami. Dekoratéry Pythonu sú druhom obalu, ktorý mení správanie funkcie. Ako zmenený objekt sa používa trieda, funkcia alebo iný dekoratér. Mali by sa používať veľmi opatrne a jasne pochopiť, čo presne je potrebné dosiahnuť. Príliš často používanie dekoratérov vedie k komplikovaniu porozumenia kódu.


Dekoratér a funkcia

Dekoračné prvky v Pythone sú funkcie, ktoré používajú inú funkciu ako argument. Ide o blok kódu, ktorý vráti určitú hodnotu.
Obsahuje argumenty, že budú použité v budúcnosti, ovplyvní návratovú hodnotu. Výstupný výstup môže byť ľubovoľného typu: zoznam, nuple, funkcia. V Pythone je každá funkcia objekt, deklaruje sa kľúčové slovo def. Rozsah hodnôt nie je uvedený v zákrutách, ale v zátvorkách. Za kľúčové slovo nasleduje názov, argumentsú uvedené v zátvorkách () za názvom. Pred prepnutím na nový riadok sa umiestni symbol ":". V Pythone nesmie byť telo prázdne, musí obsahovať zoznam príkazov. Ak chcete opustiť toto miesto, vložte prázdny preukaz operátora.

def empty_func ():

pásu

Podobný syntaxe sa vzťahuje na všetky funkcie okrem anonymné. Anonymné je nasledujúci:

func = lambda x, y: x + y

Vydané:

func (1, 2) # vracia 3

Call (druhá metóda)

(lambda x, y: x + y) (1, 2) # vráti 3[21 ]

na zdobenie spôsobená nasledujúcim spôsobom:

názov @ natierač
def yzmenyaemaya_funktsyya
yzmenyaemoy_funktsyy tela

schéma práce popísaný nasledujúci kód:

def natierač (change_funct):
def return_func1 ():
tlačovej "kód, než sa"
change_funct ()
print "kód po"
vratnej return_func1

V súlade s tým, je volanie je nasledujúci:

& lt; script async = "//pagead2.googlesyndication.com/pagead/js/a dsbygoogle.js "& gt;
<- fb_336x280_2 ->

& lt; script & gt; (adsbygoogle = window.adsbygoogle || []) stlačte ({});
@decorator
def retrurn_func1 ():
pre tlač new_change

argumenty

argumentov predaných Python dekorácie akýkoľvek typ dát.

Premenné rovnakého typu sa prekladajú čiarkami. Existuje niekoľko spôsobov, ktorými sú v parametroch špecifikované premenné hodnoty.

  1. Normálna.
  2. Pomocou kľúčových slov.
  3. Úlohy statických hodnôt.
  4. Použitie polohových prvkov.

pri vytváraní uvedených niekoľko argumentov, aby. Pri volaní parametrov sú všetky hodnoty uvedené vv správnom poradí.

def väčší (a, b):
ak a & gt; b:
vytlačiť
ďalej:
tlače B

Správny výzvou

väčší, 

(66 ) Chybné volanie:

väčší, 

väčší, (1273)

v prípade, že argumenty sú kľúčové slová z výzvu náhodne, ako je používaný hodnota určuje konkrétny názov kľúč.

def osoba (meno, vek):
print meno, "je", "vek", "let"
Osoba (vek = 23 name = "John")

Statické hodnoty premenných sa vytvárajú spolu s funkciou prostredníctvom operátora priradenia, ako keby inicializácia prebehla v tele.


Funkcie a metódy sú syntakticky podobné.

Rozdiel je v tom, že funkcia sa nazýva iba menom.

func ()

A volanie metódy sa uskutočňuje prostredníctvom operátora. " a zadá sa názov metódy, kde prvým parametrom je nadradený.

object.func ()

, a tým, Python maliari vytvoriť metódy, ako aj funkciu.

Tu sme vytvorili natierač def method_friendly_decorator (method_to_decorate):

def obal (self, lož):
leží = lož - 3 #
vratné method_to_decorate (self, lož)
vratné obal

, F je vytvorenie triedy s metódami, ktoré by neskôr boli modifikované ^

trieda Lucy (objekt):
def __init __ (self )
self.age = 32

@method_friendly_decorator
def sayYourAge (self, lož):
print "? som% S, ale koľko dáte" % (Self.age + lož)

Lucy.sayYourAge (-32)
# 26 A dal som vám, čo?

Tu je použitý formát (). Priradené k formátovanému reťazcu sa používa takto:


, s výnimkou Je tu dosť dekoratéra, niekoľko úrovní zábaly. Keď vytvoríteVstavaný dekoratér začína každý nový riadok, počet riadkov určuje úroveň obtiažnosti. Zdá sa, že toto:

@AAA
@BBB
@CCC
funkcia def ():
prechádzajú

V súlade s tým, AAA (), akceptuje parametre BBB () a spravuje CCC ().

def f ():
prechádzajú:
,
, f = (AAA BBB (CCC (funkcia))):

Funkcia prešiel tri rôznych dekoratérov, je priradený f (). Každý z nich vráti svoj výsledok, ktorý zase spracuje obal. Môžete si všimnúť, že posledný dekorátor zoznamu je prvý, začne funkciu spracovania ().

V Pythone vyzerajú triedy dekoratérov.

prejde:

C = prvý dekoračný (druhý dekoračný (CDC))
)

XX = C ()

def fn1 (Arg): návrat lambda: 'XX' + Arg ()

def FN2 (Arg): návrat lambda: ' YY '+ Arg ()

def FN3 (Arg): návrat lambda:' ZZ, + Arg ()

, 'fn1
,
,' FN2

@ FN3

def myFunc (): # myFunc = fn1 (FN2 (FN3 (myFunc)))

vratné 'Python'

tlače (myFunc ()) # zobrazenie tejto "XXYYZZPython"

V tomto prípade sa vykonávanie obalovú logika je pomocou def lambda:


& lt; script type = "text /javascript" & gt;
var blockSettings = {blockId: "R-A-70350-45", renderTo: "yandex_rtb_R-A-70350-45", asynchrónne:! 0};
, ak (document.cookie.indexOf ("abmatch =") väčšie alebo rovné 0) blockSettings.statId = 70350;
! Funkcie (a, b, c, d, e) {a [c] = a [c] || [], a [c] .push (funkcia () {Ya.Context.AdvManager.render (blockSettings)}), e = b.getElementsByTagName ("scenár") , d = b.createElement ("scenár"), d.type = "text /javascript", d.src = "//an.yandex .ru /systém /context.js "d.async = 0e.parentNode.insertBefore (d, e)} (to, this.document ,!" yandexContextAsyncCallbacks ");
lambda: 'XX' + Arg ()

FN3 () sa otáča myFunc, ZZPython vráti namiesto predchádzajúceho riadku Python. Potom začne fungovať reverzibilná fn2 (), ktorá nakoniec vracia výsledok YYZZPythonu. Na konci fn1 () spracováva myfunc () aVráti konečný výsledok - riadok XXYYZZPython.

Vstavané dekoratéry

K dispozícii sú zabudované dekorátory funkcií Pythonu. Prichádzajú spolu s tlmočníkom, aby ste ich mohli použiť na import ďalších modulov.

Staticmethod spracováva funkciu argumentu tak, že sa stáva a prijíma statický špecifikátor.

Trieda C: 

@staticmethod

def f (arg1 arg2): #static

prechádzajú
(252 ) Classmethod má triedu so spracovanou funkciou.

, trieda MyClass: 

@classmethod
,
, metóda def (CLS, arg):
,
, pre tlač ('% s classmethod% D'
cls.method



def call_class_method (
self):

self.method

trieda MySubclass (MyClass):

@classmethod

def call_original_method (CLS):

cls.method



MyClass.method

# Moje_třída classmethod. 0

MyClass.call_original_method () # MyClass classmethod. 5

MySubclass.method

# MySubclass classmethod. 0

MySubclass.call_original_method () # MySubclass classmethod. 6

# Voláme metódy triedy prostredníctvom objektu.

my_obj = MyClass ()

my_obj.method



my_obj.call_class_method ()

Každá funkcia môže byť použitá natierač.

Náhradné tvorcovia a hetterov

s triedy menovaný vlastníctva getry, regulátorov, deletterы.

pevnostnej triedy ([fget [, FSET [, fdel [, doc]]]])

getry a zápis na stroji, sú nasledujúce:

Prebieha prenos parametrov do triedy Python. Vlastník dekorácie má metódy:

  • fget - dostane hodnotu atribútu;
  • fset definuje hodnotu atribútu;
  • odstraňuje fdel;
  • doc vytvorí popis atribútu. Ak dokument nie jeje priradená, vráti kópiu popisu fget (), ak existuje.
, triedy C (objekt): 

def __init __ (self):

self._x = Žiadne

def Getxo (self):

vratné self._x

def SETX (self, hodnota):

self._x = hodnota

def delx (self):

del self._x

x = vlastníctva (Getxo, SETX, delx, "Som 'x' vlastnosť".)

za použitia dekoratér Pythonproperty:

, triedy C (objekt): 

def __init __ (self):

self._x = Žiadne

@property

def x (self):
,
, "". "som 'x' vlastnosť" ""

vratné self._x
,
, 'x.setter

def x (self, hodnota):

self._x = hodnota
,
, 'x.deleter

def x (self):

del self._x

Vlastnosť vytvorila funkcie x decorator. Keďže všetci dekoranti majú vstavaný setter, getter, deletter metódy, môžete zavolať jednému z nich.

Vlastnosti

Pri práci s dekoratérom je potrebné vziať do úvahy niektoré funkcie:

  1. Použitie dekoratérov mierne spomaľuje volanie funkcie.
  2. Po poškodení nie je možné rozdeliť poškodenú funkciu. Existujú spôsoby, ako obísť toto pravidlo. Môžete vytvoriť dekorátor, ktorý môžete neskôr odpojiť od funkcie. Ale to nie je veľmi dobrá prax.
  3. Vzhľadom na skutočnosť, že dekorant rotuje funkciu, ladenie môže byť komplikované. Problém je vyriešený pomocou modulu functools.

Modul functools je zbierka metód, ktorá poskytuje interakciu s inými funkciami a je tiež dekorátorom Pythonu.

Užitočná metóda cmp_to_key (func) konvertuje kláves cmp () (). Obe metódy slúžia na triedenie zoznamu, ale prvý sa odstráni z Pythonu 3.0 a druhý sa pridá do verzie 2. Lru_cache uloží poslednýhovory do vyrovnávacej pamäte. Ak je maxsixe zadaný ako none, veľkosť vyrovnávacej pamäte sa zvyšuje neurčito. Slovník sa používa na ukladanie často používaných dopytov. Ak je argument zadaný = true, argumenty rôznych typov sa ukladajú do vyrovnávacej pamäte samostatne. Preto keď sú zadané pravdivé, uložia sa do jedného zoznamu.

Total_ordering zdobí triedu, ktorá obsahuje porovnávacie metódy a pridá všetky ostatné.

čiastočnú (Func, * args **, kľúčové slová) vráti funkciu, ktorá spôsobené prvý argument oblasti parametre metódy, prenáša pozičné * args, ktorá je daná jedna, a tzv kwargs.

Zníženie funguje takto:

znižuje (lambda x, y: x + y, [1, 2, 3, 4, 5])
(375 ) Ekvivalent:

((((1 + 2) 3) 4) 5)

Zníženie dôsledne použitie úkon párov predmety uvedené v zozname * * kľúčové slová alebo všetky položky * args. Tak vo vyššie uvedenom príklade použitia funkcie lambda ovládal prvé dva prvky:

1 + 2

, potom sa výsledok sčítaného s tretím prijatého tohto výsledku sa pridá k nasledujúcemu prvky, atď.

Update_wrapper aktualizuje shell tak, aby sa podobal na zabalenú funkciu. Argumenty špecifikujú tieto dve funkcie, kopírované a aktualizované atribúty.

, priradenej = WRAPPER_ASSIGNMENTS

kolóny WRAPPER_ASSIGNMENTS obsahuje predvolené hodnoty __name__, __module__, __annotations__ a __doc__.

aktualizované = WRAPPER_UPDATES

K WRAPPER_UPDATES uvedené atribúty aktualizované východiskové __dict__.

Obálky nazývajú čiastočne ako dekoratér.

Dekoratívna manipulácia s chybami

Možnosti dekoratérov vám umožnia vytvoriťFunkcia, ktorá v prípade chyby dáva jeden výsledok, pokiaľ nie je chyba - na strane druhej.

Realizácia:

dovozné functools def opakovať (func): @ functools.wraps (func) def obalu (* args, ** kwargs): kým True: pokúsiť : návrat FUNC (* args, ** kwargs) s výnimkou výnimka: priechod vratného obalu

ukazuje, že v prípade funkcie výnimky začína znovu.

@retry def do_something_unreliable (): ak random.randint (010) & gt; 1: zvýšiť IOError ("Broken omáčku, všetko je hosed !!! 111one") else: return "Úžasné omáčku!" tlač (do_something_unreliable ())

Tento kód znamená, že 9 z 11 prípadov, dôjde k chybe.

def my_decorator (fn): def zabalené (): try: return fn () s výnimkou Exception e: print ("Chyba:", e) návrat zabalený @my_decorator def my_func (): import náhodný, zatiaľ čo pravda: ak random.randint (0 4) == 0: zvýšiť výnimka (! 'random') print ('OK') my_func ()

dostanete konzoly:

OK OK OK Chyba: Random!

vytvorením jeho natierač

natierač je funkcia, ktorá sa nachádza v inej funkcie pomocou vhodných metód.

Príklad natierač Python:

def my_shiny_new_decorator (function_to_decorate): 

def the_wrapper_around_the_original_function ()

pre tlač ("I - kód, ktorý je spustený pre funkciu volanie ")

function_to_decorate ()

print (" I - kód, ktorý pracuje na ")

return the_wrapper_around_the_original_function

v tomto kóde maliar je my_shiny_new_decorator (). Ďalej zdobia function_to_decorate () z parametrov poľa. the_wrapper_around_the_original_function - je príkladom toho, ako má byť liečený dekoryruemaya funkciu. V tomto prípade, ktorý znie:

print ("I - kód, ktorý je spustený pre funkciu volanie") 

print ("I - kód, ktorý pracuje na")

My_shiny_new_decorator () vracia dekoruyemu the_wrapper_around_the_original_function ().

KAk chcete vyriešiť nejakú funkciu, otočí ju.

stand_alone_function = my_shiny_new_decorator (stand_alone_function)

V tomto prípade, dekorovaný funkcie - stand_alone_function, natierač - je my_shiny_new_decorator. Hodnota je priradená premennej stand_alone_function.

def stand_alone_function () 

print ("Som prostý jediné funkcie, pretože nemáte posmeesh zmením?")

stand_alone_function ()
I - kód pre spustenie pre volanie funkcie 

som jednoduchý single funkcie, pretože nemáte posmeesh zmením?

I - kód, ktorý sa spustí po


Je teda jasné, že stand_alone_function, ktorý podráždený obrazovky jednu vetu, sa teraz zobrazuje tri návrhy. To sa deje pomocou dekorátora.

Súvisiace publikácie