Python dekoraterji - je to kaj?

Dekorater je predloga, ki povezuje dodatno obnašanje z objektom. Uporablja se v mnogih jezikih OOP-a: Java, C #, PHP, JS. Python ni izjema. Naloga dekoraterjev je opisana v naslednjem primeru. Obstaja objekt, ki opravlja neko funkcijo, med razvojem programa mu morate dodati nekaj dodatnih funkcij. Izvede se lahko pred ali po ali celo med glavnimi funkcijami. Dekoraterji se uporabljajo za reševanje tega problema. Razširijo funkcionalnost in tako odpravijo ustvarjanje drugega istega razreda z dodatnimi metodami. Dekoraterji Python so nekakšen ovoj, ki spremeni obnašanje funkcije. Kot spremenjeni predmet se uporablja razred, funkcija ali drugi dekorater. Uporabljati jih je treba zelo previdno z jasnim razumevanjem, kaj natančno je treba doseči. Prepogosto je uporaba dekoraterjev zapletla razumevanje kode.


Dekorater in funkcija

Dekoraterji v Pythonu je funkcija, ki kot argument uporablja drugo funkcijo. Gre za blok kode, ki vrne določeno vrednost.
Vsebuje argumente, ki bodo uporabljeni v prihodnosti, ki bodo vplivali na vrnjeno vrednost. Izhodni izhod je lahko poljuben: seznam, tuple, funkcija. V Pythonu je vsaka funkcija objekt, deklarira pa ga ključna beseda def. Obseg vrednosti ni podan z zavitimi oklepaji, ampak z zavihkom z zarezami. Ključni besedi sledi ime, argumentso podani v oklepajih () za imenom. Pred preklopom na novo vrstico se postavi simbol ":". V Pythonu telo ne more biti prazno, mora vsebovati seznam ukazov. Če želite zapustiti ta kraj, dajte prazno vozovnico.

def empty_func ():

pass

Podobna skladnja se razširi na vse funkcije razen anonimne. Anonymous izgleda takole:

func = lambda x, y: x + y

Pokliči:

func (1 2) # vrne 3

Izziv (druga metoda):

(lambda x, y: x + y) (1 2) # vrne 3
]

Dekoraterji se imenujejo, kot sledi:

@ ime dekoraterja
def spremenjena funkcija
telo spremenljive funkcije

Shema dela je opisana z naslednjo kodo:

def defator (change_funct):
def return_func1 ():
natisni "kodo pred"
change_funct ()
natisni "code after"
vrni return_func1

V skladu s tem je poziv naslednji:

& lt; skript async = "//pagead2.googlesyndication.com/pagead/js/a dsbygoogle.js "& gt;
& lt ;! - fb_336x280_2 - & gt;

& lt; skript & gt; (adsbygoogle = window.adsbygoogle || []). push ({});
@decorator
def retrurn_func1 ():
print new_change

Argumenti funkcije

V argumentih dekoraterjev Python, katere koli vrste podatkov.

Spremenljivke iste vrste se prevedejo z vejicami. Obstaja več načinov, v katerih so v parametrih podane vrednosti spremenljivk.

  1. Normalno.
  2. S pomočjo ključnih besed.
  3. Naloge statičnih vrednosti.
  4. Uporaba pozicijskih elementov.

Pri ustvarjanju je v določenem vrstnem redu podanih več argumentov. Pri klicanju parametrov so vse vrednosti podane vv pravilnem vrstnem redu.

def večje (a, b):
če a & gt; b:
natisni a
drugo:
natisni b

pravilen klic:

večji 

) Napačen klic:

večji 

večji (1273)

Če so uporabljeni argumenti ključne besede, se njihov klic izvede samovoljno, vrednost podaja določeno ime-ključ.

def oseba (ime, starost):
tiskano ime, "je", "starost", "starost"
oseba (starost = 23 ime = "John") 72]

Statične vrednosti spremenljivk se ustvarijo skupaj s funkcijo prek operaterja dodelitve, kot če bi bila inicializacija izvedena v telesu.


& lt; skript type = "text /javascript" & gt;
lahko blockSettings2 = {blockId: "R-A-70350-39", renderTo: "yandex_rtb_R-A-70350-39", async:! 0};
if (document.cookie.indexOf ("abmatch =") & gt; = 0) blockSettings2.statId = 70350;
Funkcija (a, b, c, d, e) {a [c] = a [c] || [], a [c] .push (funkcija () {Ya.Context.AdvManager.render (blockSettings2)}), e = b.getElementsByTagName ("script") , d = b.createElement ("script"), d.type = "text /javascript", d.src = "//an.yandex .ru /system /context.js ", d.async =! 0e.parentNode.insertBefore (d, e)} (ta, ta.dokument," yandexContextAsyncCallbacks ");
def prostor (ime-plan, center = "zvezda"):
print (ime-planeta, "kroži okoli", center)
prostor (Mars)
]

Če argumenti niso znani na stopnji ustvarjanja funkcije, se uporabljajo argumenti. Lahko označijo več spremenljivk istega tipa ali seznama:

def func (* args):
return args
func (123 'abc')
# (123 'abc') )
func


#

Vrednosti tipk se prenašajo na podoben način - z znakom "**".

Spremenljivke, določene v telesu, so lokalne, uporabljajo pa jih same funkcije. Za ustvarjanje globalne spremenljivke se uporablja globalni specifikator.

def get_older ():
svetovna starost
starost + = 1

Podprtorekurzija

def fact (num):
če num == 0:
vrne 1
drugo:
vrne num * fact (num - 1)
101]

Dekoracija metod

Funkcije in metode so skladenjsko podobne.

Razlika je v tem, da se funkcija imenuje samo po imenu.

func ()

Klic metode se izvaja prek operaterja "." in vnesemo ime metode, kjer je prvi parameter matični.

object.func ()

Tako so Python dekoraterji za metode ustvarjeni tako kot za funkcijo.

Tukaj smo ustvarili metodo branilca dekorja method_friendly_decorator (method_to_decorate):

def wrapper (self, lie):
lie = lie - 3 #
return method_to_decorate (self, lie
return wrapper

F tukaj je ustvaril razred z metodami, ki bodo kasneje spremenjene ^

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

@method_friendly_decorator
def sayYAge (self, lie):
natisni "Sem% s, koliko si dal?" % (self.age + lie)

Lucy.sayYourAge (-32)
# Imam 26 let in koliko ste dali?

Uporabljen je format (). Dodeljene so nizom formatov, ki se uporabljajo na naslednji način:


& lt; script type = "text /javascript" & gt;
lahko blockSettings3 = {blockId: "R-A-70350-44", renderTo: "yandex_rtb_R-A-70350-44", async:! 0};
if (document.cookie.indexOf ("abmatch ="))> = 0) blockSettings3.statId = 70350;
Funkcija (a, b, c, d, e) {a [c] = a [c] || [], a [c] .push (funkcija () {Ya.Context.AdvManager.render (blockSettings3)}), e = b.getElementsByTagName ("script") , d = b.createElement ("script"), d.type = "text /javascript", d.src = "//an.yandex .ru /system /context.js ", d.async =! 0e.parentNode.insertBefore (d, e)} (ta, ta.dokument," yandexContextAsyncCallbacks ");
print ("string {} {}") Format (1 2)
#string 1 2

V tem primeru je format () dve števki: 1 2. Zamenjujeta znake {} v vrstnem redu, v katerem se nahajata. Oblikovanje je na voljoizključno za elemente nizov. To pomeni, da argument postane prvo mesto kodrastih oklepajev, druga pa druga. V načinu formatiranja je mogoče spremeniti vrstni red vstavljanja vrednosti. To naredimo preko indeksov.

Če:

print ("string {} {}"). Format (1 2)
#string 1 2

: R3r3r3701.

print ("niz {1} {0}".) Format (1 2)
#string 2 1

Vrstice je mogoče formatirati skozi imena ključev v formatu (arg1 = vrednost1 arg2 = vrednost2).

print ("string {arg1} {arg2}") Format (arg1 = 1 arg2 = 2)
#string 1 2

Lahko uporabite mešano sistem - če ima v dveh argumentih samo ena od njih statično vrednost. Za prenos vrednosti označuje indeks in ime spremenljivke.

& lt; skript async = "//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js">

& lt; skript & gt; (adsbygoogle = window.adsbygoogle || []). push ({});
print ("string {arg1} {1}".) Format (arg1 = 1 2)
#string 1 2

Dekoraterji z argumenti

]

Argumente lahko pošljete dekoraterjem Python, ki naknadno spremenijo obdelano funkcijo.

def decator (function_to_decorate):
def funkcija (arg1 arg2):
natisni "glej, kaj sem dobila:", arg1 arg2
povratna funkcija
]

V tem primeru obstaja @decorator, ki spremeni funkcijo. Argumenti so preskočeni v drugi vrstici, ki jih prenaša spremenljivka function_to_decorate.

@decorator
def real_func (Peter Ivanovič)
natisni "Moje ime", arg1 arg2

Na zaslonu se bo pojavil:

Poglejte, kaj sem dobil: Peter Ivanovič 

Moje ime je Peter Ivanovič

Vgrajeni dekoraterji

Dovolj je en dekorater, realizira se več nivojev oblog. Ko ustvariteVsak vdelani dekorater se začne z novo vrstico, število vrstic določa stopnjo zahtevnosti. Izgleda takole:

@AAA
@BBB
@CCC
def funkcija ():
mimo:

V skladu s tem, AAA ), sprejema parametre BBB () in obdeluje CCC ().

def f ():
mimo:

f = (AAA BBB (CCC (funkcija))):

Funkcija se prenaša s tremi različnih dekoraterjev, je dodeljena f (). Vsak od njih vrne svoj rezultat, ki nato obdela ovoj. Opazite lahko, da je zadnji dekorater na seznamu prvi, začne obdelovati funkcijo ().

V Pythonu pogledajo tudi dekoraterji razredov.

mimo:

C = prvi dekorator (drugi dekorator (CDC))
)

XX = C ()

def fn1 (arg): povratna lambda: 'XX' + arg ()

def fn2 (arg): return lambda: ' YY '+ arg ()

def fn3 (arg): povratna lambda:' ZZ '+ arg ()

@ fn1

@ fn2

@ fn3

def myfunc (): # myfunc = fn1 (fn2 (fn3 (myfunc)))

vrne se 'Python'

print (myfunc ()) # "XXYYZZPython"

V tem primeru se izvajanje logike prelamljanja izvede z uporabo def lambda:


& lt; script type = "text /javascript" & gt;
lahko blockSettings = {blockId: "R-A-70350-45", renderTo: "yandex_rtb_R-A-70350-45", async:! 0};
if (document.cookie.indexOf ("abmatch ="))> = 0) blockSettings.statId = 70350;
Funkcija (a, b, c, d, e) {a [c] = a [c] || [], a [c] .push (funkcija () {Ya.Context.AdvManager.render (blockSettings}), e = b.getElementsByTagName ("script") , d = b.createElement ("script"), d.type = "text /javascript", d.src = "//an.yandex .ru /system /context.js ", d.async =! 0e.parentNode.insertBefore (d, e)} (ta, ta.dokument," yandexContextAsyncCallbacks ");
lambda: 'XX' + arg ()

Fn3 () vrti myfunc, vrne ZZPython namesto prejšnje vrstice Pythona. Nato začne delovati reverzibilna fn2 (), ki sčasoma vrne rezultat YYZZPython. Na koncu fn1 () obdeluje myfunc () inVrne končni rezultat - vrstico XXYYZZPython.

Vgrajeni dekoraterji

Vgrajeni so dekoraterji funkcij Pythona. Pridejo skupaj s tolmačem, da jih lahko uporabite za uvoz dodatnih modulov.

Staticmethod obravnava funkcijo argumenta tako, da postane statična in sprejme statični specifikator.

razred C: 

@staticmethod

def f (arg1 arg2): #static

pass

) Classmethod naredi razred z obdelano funkcijo.

razred MyClass: 

@classmethod

def metoda (cls, arg):

print ('% s classmethod.
cls.method



def call_class_method (
self: method

self.method

razred MySubclass (MyClass):

@classmethod

def call_original_method (cls):

cls.method



Razredni metod. 0

MyClass.call_original_method () # razred mojega razreda. 5

MySubclass.method

# Metoda razreda mojih razredov. 0

MySubclass.call_original_method () # Metoda razreda mojih razredov. 6

# Metode razredov imenujemo skozi objekt.

my_obj = MyClass ()

my_obj.method



my_obj.call_class_method ()

dekorater

Nadomestitev usedlin in gnojil

S pomočjo razreda lastnine, ki so ga imenovali bralci, pisalniki, pisalniki.

lastnost razreda ([fget [, fset [, fdel [, doc]]]])]

Noge in nastavitve TypeScript so naslednje:

Izvede se prenos parametrov v razred Python. Dekorater nepremičnine ima metode:

  • fget - dobi vrednost atributa;
  • fset definira vrednost atributa;
  • odstrani fdel;
  • doc ustvari opis atributa. Če dokument nije dodeljena, vrne kopijo opisne fget (), če jo obstaja.

razred C (objekt):

Def __init __ (samo):

self._x = nič

def getx (self):


def-setx (samo) vrednost:

self._x = vrednost

def delx (self):

za self._x

x = lastnost (getx, setx, delx, "jaz sem lastnost" x ".))

Uporaba lastnosti Python kot dekoraterja:


razred C (objekt): 

def __init __ (self):

self._x = nič

@property

def x (self):

"" "Jaz sem lastnina 'x'." ""

vrne self._x

@ x.setter

349) def x (self, value):

self._x = vrednost

@ x.deleter

def x (self):

del self._x

Nepremičnina je ustvarila funkcije x dekorater. Ker imajo vsi dekoraterji vgrajen setter, getter, deletter metode, lahko pokličete enega od njih.

Lastnosti

Pri delu z dekoraterjem morate upoštevati nekatere značilnosti:

  1. Uporaba dekoraterjev rahlo upočasni klic funkcije.
  2. Ko poškodovane funkcije ni mogoče razdeliti. Obstajajo načini za izogibanje temu pravilu. Ustvarite lahko dekorater, ki ga lahko kasneje prekinete. Toda to ni zelo dobra praksa.
  3. Ker dekorater zavrti funkcijo, je lahko odpravljanje napak zapleteno. Problem je rešen z modulom functools.

Modul functools je zbirka metod, ki omogočajo interakcijo z drugimi funkcijami in je tudi dekorater Python.

Uporabna metoda cmp_to_key (func) pretvori ključ cmp () (). Obe metodi sta za razvrščanje seznama, vendar je prva odstranjena iz Pythona 3.0, druga pa je dodana v različici 2. Lru_cache shrani zadnjipredpomnilnika. Če je maxsixe podan kot none, se velikost predpomnilnika neomejeno poveča. Slovar se uporablja za shranjevanje pogosto uporabljenih poizvedb. Če je argument vnesen = true, so argumenti različnih vrst predpomnjeni ločeno. V skladu s tem, ko so vneseni = true, so shranjeni v enem seznamu.

Total_ordering krasi razred, ki vsebuje metode primerjave, in dodaja vse ostale.

Parcialne (func, * args, ** keywords) vrne funkcijo, ki jo imenuje prvi argument, iz obsega parametrov metode, posreduje pozicijske * argumente, ki jih podaja drugi, in imenovane kwargs.

Zmanjšanje deluje tako:

zmanjša (lambda x, y: x + y, [1, 2, 3, 4, 5])

) Ekvivalent:

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

Zmanjša uporabo podane funkcije v zaporedju parov elementov, navedenih v * * ključne besede ali vse postavke * args. Tako se v zgornjem primeru ob uporabi lambda funkcije obdelata prva dva elementa:

1 + 2

Naslednji rezultat se sešteje s tretjim, rezultat, dobljen iz tega rezultata, se doda naslednjemu:

Update_wrapper posodobi lupino tako, da je podobna oviti funkciji. Argumenti določajo ti dve funkciji, kopirane in posodobljene atribute.

dodeljena = WRAPPER_ASSIGNMENTS

Zaporka WRAPPER_ASSIGNMENTS vsebuje privzete vrednosti za __name__, __module__, __annotations__ in __doc__.

updated = WRAPPER_UPDATES

WRAPPER_UPDATES označuje atribute, ki so posodobljeni, privzeto je __dict__.

Obloge imenujejo delne kot dekorater.

Dekorater za ravnanje z napakami

Možnosti dekoraterjev vam omogočajo, da jih ustvaritefunkcijo, ki v primeru napake povzroči en rezultat, če ni napak, v drugo.

Izvedba:

uvozni functools def ponoviti (func): @ functools.wraps (func) def zavitka (* argumentov ** kwargs): medtem Res: poskusiti : nazaj func (* argumenta, ** kwargs) razen izjema: povratni akcije ovojem

kaže, da če izjeme funkcija ponovno zažene.

@retry def do_something_unreliable (): če je random.randint (010) & gt; 1: dvignite IOError ("Broken omaka, vse je hosed! 111one") drugo: vrnite "Awesome omaka!" print (do_something_unreliable ())

Ta koda pomeni, da bo 9 od 11 primerov naletelo na napako.

def my_decorator (fn): def zaviti (): poskusite: povratni fn (), razen kot Izjema e: print ("Napaka:«, e) vrnitev zavita @my_decorator def my_func (): uvoz naključno pa res: če random.randint (0 4) == 0: dvig Exception ('! random ") print (' v redu ') my_func ()

, boste prejeli konzolo:

Ok Ok Ok Ok: Naključno!

Vzpostavitev svojo pleskar

pleskar je funkcija, ki je nameščena znotraj druge funkcije z ustreznimi metodami.

PRIMER pleskar v Python:

def my_shiny_new_decorator (function_to_decorate): 

def the_wrapper_around_the_original_function ():

za tiskanje ("I - koda, ki je kandidiral za funkcijo klica ")

function_to_decorate ()

print (" I - koda, ki deluje na ")

vrnitev the_wrapper_around_the_original_function

V tej kodi je dekorater moj_shiny_new_decorator (). Kasneje dekorira funkcijo_dokumente () iz območja parametrov. The_wrapper_around_the_original_function je primer, kako bo obdelana dekorirana funkcija. V tem primeru, je dodal:

print ("I - koda, ki je kandidiral za funkcijo klica") 

print ("I - koda, ki deluje na")

My_shiny_new_decorator () vrne dekoruyemu the_wrapper_around_the_original_function ().

DoČe želite izvesti katerokoli funkcijo, postane dekorater.

stand_alone_function = my_shiny_new_decorator (stand_alone_function)

V tem primeru je funkcija set-stand_alone_function, dekorater je my_shiny_new_decorator. Vrednost je dodeljena spremenljivki stand_alone_function.

def stand_alone_function (): 

print ("Jaz sem preprosta, osamljena funkcija, si me ne drzite spremeniti?")

stand_alone_function ()
435]
Sem koda, ki deluje pred klicanjem funkcije 

Sem preprosta osamljena funkcija, ker me ne boste upali spremeniti?

In jaz sem koda, ki deluje po


Torej je očitno, da stand_alone_function, ki prikaže en stavek, zdaj prikaže tri stavke. To naredite s pomočjo dekoraterja.

Sorodne publikacije