Dekorater je predložak dizajniran za povezivanje dodatnog ponašanja s objektom. Koristi se u mnogim jezicima OOP-a: Java, C #, PHP, JS. Python nije iznimka. Zadatak dekoratera može se opisati u sljedećem primjeru. Postoji objekt koji obavlja neku funkciju, za vrijeme razvoja programa morate dodati neke dodatne funkcionalnosti. Može se izvršiti prije ili poslije, ili čak tijekom glavnih funkcija. Dekoratori se koriste za rješavanje ovog problema. Oni proširuju funkcionalnost, eliminirajući stvaranje drugog istog razreda s dodatnim metodama. Python dekoratori su vrsta omotača koji mijenja ponašanje funkcije. Kao promijenjeni objekt koristi se klasa, funkcija ili drugi dekorater. Trebalo bi ih vrlo pažljivo koristiti s jasnim razumijevanjem o tome što točno treba postići. Često upotreba dekoratera dovodi do komplikacije razumijevanja koda.
Dekorater i funkcija
def empty_func ():
pass
Slična sintaksa proteže se na sve funkcije osim anonimne. Anonimno izgleda ovako:
func = lambda x, y: x + y
Nazovi:
func (1 2) # return 3
Izazov (druga metoda):
(lambda x, y: x + y) (1 2) # vraća 3
@ ime dekora
def modificirana funkcija
tijelo varijabilne funkcije
Shema rada opisana je sljedećim kodom:
def defator (change_funct):
def return_func1 ():
print "code before"
change_funct ()
print "code after"
povratak return_func1
Prema tome, poziv je sljedeći:
& lt ;! - fb_336x280_2 - & gt;
& lt; skripta & gt; (adsbygoogle = window.adsbygoogle || []). push ({});
@decorator
def retrurn_func1 ():
print new_change
Argumenti funkcije
U argumentima Python dekoratora, bilo koji tip podaci.
Varijable istog tipa prevedene su zarezima. Postoji nekoliko načina na koje su vrijednosti parametara navedene u parametrima.
- Normalno.
- Uz pomoć ključnih riječi.
- Zadaci statičkih vrijednosti.
- Uporaba pozicijskih elemenata.
Prilikom izrade, nekoliko je argumenata specificirano u određenom poretku. Kada pozivate parametre, sve su vrijednosti navedene uu ispravnom redoslijedu.
def veći (a, b):
ako je a & gt; b:
ispiši
drugo:
ispiši b
ispravan poziv:
veći
) Pogrešan poziv:
veći
veći (1273)
Ako su korišteni argumenti ključne riječi, njihov se poziv izvodi proizvoljno, vrijednost specificira određeni naziv-ključ.
def osoba (ime, dob):
ime ispisa, "is", "age", "years old"
osoba (dob = 23 ime = "John") 72]
Statičke vrijednosti varijabli stvaraju se zajedno s funkcijom preko operatora dodjele kao da se inicijalizacija odvijala u tijelu.
& lt; script type = "text /javascript" & gt;
može 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)} (ovaj, ovaj.dokument," yandexContextAsyncCallbacks ");
def prostor (ime_plana, centar = "zvijezda"):
print (ime-planeta, "orbitira", centar)
prostor (Mars)
]Kada argumenti nisu poznati u fazi stvaranja funkcije, koriste se argumenti. Mogu označiti nekoliko varijabli istog tipa ili popisa:
def func (* args):
return args
func (123 'abc')
# (123 'abc') )
func
#
Vrijednosti tipki prenose se na sličan način - koristeći znak "**".
Varijable specificirane u tijelu su lokalne, a izravno ih koristi sama funkcija. Za kreiranje globalne varijable koristi se globalni specifikator.
def get_older ():
globalna dob
dob + = 1
Podržanorekurzija.
def fact (num):
ako je num == 0:
povratak 1
drugo:
povratak num * fact (num - 1)
101]Dekoracija metoda
Funkcije i metode su sintaktički slične.
Razlika je u tome što se funkcija naziva samo imenom.
func ()
Poziv metode provodi se kroz operatora "." i ime metode se upisuje, gdje je prvi parametar roditelj.
object.func ()
Dakle, Python dekoratori za metode su stvoreni kao i za funkciju.
Ovdje smo stvorili dekorativnu metodu branitelja method_friendly_decorator (method_to_decorate):
def wrapper (self, lie):
lie = lie - 3 #
return method_to_decorate (self, lie
povratni omotač
F ovdje je stvorio klasu s metodama koje će kasnije biti modificirane ^
klasa Lucy (objekt):
def __init __ (self) ):
self.age = 32
@method_friendly_decorator
def kažeVaše (samo, laž):
print "Ja sam% s, koliko si dao?" % (self.age + lie)
Lucy.sayYourAge (-32)
# Ja sam 26 i koliko ste dali?
Ovdje se koristi format (). Dodijeljeni za nizove formata, koji se koriste na sljedeći način:
& lt; script type = "text /javascript" & gt;
može blockSettings3 = {blockId: "R-A-70350-44", renderTo: "yandex_rtb_R-A-70350-44", async:! 0};
ako (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)} (ovaj, ovaj.dokument," yandexContextAsyncCallbacks ");
print ("string {} {}") Format (1 2)
#string 1 2
U ovom primjeru format () dvije znamenke: 1 2. Zamjenjuju znakove {} redoslijedom kojim se nalaze. Formatiranje je dostupnoisključivo za gudače. To jest, argument postaje prvo mjesto vitičastih zagrada {}, a drugi - drugi. U načinu formatiranja moguće je promijeniti redoslijed umetanja vrijednosti. To se radi preko indeksa.
Ako:
print ("string {} {}") Format (1 2)
#string 1 2
: R3r3r3701.
print ("string {1} {0}".) Format (1 2)
#string 2 1
Dopušteno je formatirati linije kroz imena ključeva u formatu (arg1 = vrijednost1 arg2 = vrijednost2).
print ("string {arg1} {arg2}") Format (arg1 = 1 arg2 = 2)
#string 1 2
sustav - kada u dva argumenta samo jedna od njih ima statičku vrijednost. Za prijenos vrijednosti označava se indeks i naziv varijable.
& lt; skripta async = "//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js">
& lt; skripta & gt; (adsbygoogle = window.adsbygoogle || []). push ({});print ("string {arg1} {1}".) Format (arg1 = 1 2)
#string 1 2
Dekorateri s argumentima
]Argumente možete poslati Python dekoraterima, koji naknadno modificiraju obrađenu funkciju.
def decator (function_to_decorate):
]
def funkcija (arg1 arg2):
print "Vidi što sam dobio:", arg1 arg2
povratna funkcijaU tom slučaju postoji @decorator koji modificira funkciju. Argumenti su preskočeni na drugom retku, a prenosi ih varijabla function_to_decorate.
@decorator
def real_func (Peter Ivanovič)
print "Moje ime", arg1 arg2Na zaslonu će se pojaviti:
Vidi što sam dobio: Peter Ivanovich
Moje ime je Peter IvanovichUgrađeni dekoratori
Dovoljno je jednog dekoratera, realizirano je nekoliko razina obloga. Kada stvarateSvaki ugrađeni dekorator započinje s novom linijom, broj redaka određuje razinu težine. Izgleda ovako:
@AAA
@BBB
@CCC
def funkcija ():
pass:U skladu s tim, AAA ), prihvaća BBB () parametre i obrađuje CCC ().
def f ():
pass:
f = (AAA BBB (CCC (funkcija))):Funkcija se prenosi s tri različitim dekoraterima, dodjeljuje se f (). Svaki od njih vraća svoj rezultat, koji pak zauzima omot. Možete primijetiti da je posljednji dekorater popisa prvi, on počinje funkciju obrade ().
U Pythonu izgledaju i klasni dekoratori.
prolaz:
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)))
povratak 'Python'
print (myfunc ()) # "XXYYZZPython"
U ovom slučaju, implementacija logike prelamanja događa se pomoću def lambda:
& lt; script type = "text /javascript" & gt;
može 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)} (ovaj, ovaj.dokument," yandexContextAsyncCallbacks ");
Lambda: 'XX' + arg ()
Fn3 () rotira myfunc, vraća ZZPython umjesto prethodnog retka Pythona. Tada reverzibilni fn2 () počinje raditi, što na kraju vraća rezultat YYZZPython. Na kraju fn1 () obrađuje myfunc () iVraća krajnji rezultat - liniju XXYYZZPython.
Ugrađeni dekoratori
Postoje ugrađeni dekoratori Python funkcija. Oni dolaze zajedno s tumačem, da biste ih mogli koristiti za uvoz dodatnih modula.
Staticmethod upravlja funkcijom argumenta tako da ona postaje statična i prihvaća statički specifikator.
klasa C:
@staticmethod
def f (arg1 arg2): #static
pass
) Classmethod čini klasu s obrađenom funkcijom.
class MyClass:
@classmethod
def metoda (cls, arg):
print ('% s classmethod.
cls.method
def call_class_method (
self: method
self.method
klasa (MyClass):
@classmethod
def call_original_method (cls):
cls.method
Klasa metode MyClass.method# MyClass. 0
MyClass.call_original_method () # klasa klase MyClass. 5
MySubclass.method
# klasa klase MySubclass. 0
MySubclass.call_original_method () #Klasa metode MySubclass. 6
# Klasne metode nazivamo kroz objekt.
my_obj = MyClass ()
my_obj.method
my_obj.call_class_method ()
dekoraciju.
Zamjena taložnika i rastvarača
Uz pomoć razreda imovine imenovanih bajtovi, postavljači, delleteri.
svojstvo klase ([fget [, fset [, fdel [, doc]]]])]
Tipografske noge i postavke su sljedeće:
Prijenos parametara na Python klasu se provodi. Uređaj za dekoraciju nekretnina ima metode:
- fget - dobiva vrijednost atributa;
- fset definira vrijednost atributa;
- fdel uklanja;
- doc stvara opis atributa. Ako dokument nijeje dodijeljena, vraća kopiju opisa fget (), ako postoji.
klasa C (objekt):
Def __init __ (self):
self._x = ništa
def getx (self):
def-setx (samo) vrijednost:
self._x = vrijednost
def delx (self):
za self._x
x = svojstvo (getx, setx, delx, "Ja sam svojstvo" x ".))
Korištenje Pythonovih svojstava kao dekoratera:
klasa C (objekt):
def __init __ (self):
self._x = None
@property
def x (self):
"" "Ja sam 'x' svojstvo." ""
povratak self._x
@ x.setter
349) def x (self, value):
self._x = vrijednost
@ x.deleter
def x (self):
self._x
Svojstvo je stvorilo funkcije x dekorater. Budući da svi dekoratori imaju ugrađeni setter, getter, deletter metode, možete pozvati jednu od njih.
Značajke
Prilikom rada s dekoratorom morate uzeti u obzir neke značajke:
- Korištenje dekoratera malo usporava poziv funkcije.
- Nakon što se oštećena funkcija ne može razdijeliti. Postoje načini zaobići ovo pravilo. Možete stvoriti dekorater koji kasnije možete odvojiti od funkcije. Ali to nije dobra praksa.
- Zbog činjenice da dekorater okreće funkciju, otklanjanje pogrešaka može biti komplicirano. Problem se rješava pomoću modula functools.
Functools modul je skup metoda koje omogućuju interakciju s drugim funkcijama, a također je i Python dekorater.
Korisna metoda cmp_to_key (func) pretvara cmp () ključ (). Obje metode služe za sortiranje popisa, ali prva je uklonjena iz Pythona 3.0, a druga je dodana u verziji 2. Lru_cache pohranjuje posljednjepoziva u predmemoriju. Ako je maxsixe naveden kao none, veličina predmemorije se povećava neograničeno. Rječnik se koristi za spremanje često korištenih upita. Ako je argument typed = true, argumenti različitih tipova su zasebno predmemorirani. Prema tome, kada se upisuje = true, pohranjuju se u jedan popis.
Total_ordering ukrašava klasu koja sadrži metode usporedbe i dodaje sve ostale.
Djelomične (func, * args, ** keywords) vraćaju funkciju koju je pozvao prvi argument iz opsega parametara metode, prosljeđuje pozicijske * argumente, koje je dao drugi, i nazvane kwargs.
Redukcija radi ovako:
smanjuje (lambda x, y: x + y, [1, 2, 3, 4, 5])
) Ekvivalent:
((((+1 +2) +3) +4) +5)
Smanjenje koristi zadanu funkciju u nizu parova elemenata navedenih u * * ključne riječi ili sve stavke * args. Dakle, u gornjem primjeru, koristeći lambda funkciju, obrađena su prva dva elementa:
1 + 2
Sljedeći rezultat se zbraja s trećim, rezultat dobiven iz tog rezultata dodaje se sljedećem:
Update_wrapper ažurira ljusku tako da podsjeća na omotanu funkciju. Argumenti određuju ove dvije funkcije, kopirane i ažurirane atribute.
dodijeljena = WRAPPER_ASSIGNMENTS
Kolica WRAPPER_ASSIGNMENTS sadrži zadane vrijednosti za __name__, __module__, __annotations__ i __doc__.
ažurirano = WRAPPER_UPDATES
WRAPPER_UPDATES označava ažurirane atribute, po defaultu je __dict__.
Oblozi nazivaju djelomični dekorater.
Uređaj za uklanjanje pogrešaka
Mogućnosti dekoratera omogućuju vam da ih stvoritefunkcija koja, u slučaju pogreške, proizvede jedan rezultat, ako nema grešaka, u drugi.
Implementacija:
import functools def retry (func): @ functools.wraps (func) def wrapper (* args, ** kwargs): dok je True: pokušaj : return func (* args, ** kwargs) osim Exception: pass return wrapper
Vidljivo je da se u slučaju iznimaka funkcija ponovno pokreće.
@retry def do_something_unreliable (): ako je random.randint (010) & gt; 1: podignite IOError ("Slomljeno umak, sve je obloženo!") Drugo: vratite "Strašan umak!" print (do_something_unreliable ())
Ovaj kod znači da će 9 od 11 slučajeva naići na pogrešku.
def my_decorator (fn): def wrapped (): pokušaj: vrati fn () osim kao iznimka e: print ("Error:", e) vrati wrapped @ my_decorator def my_func (): import random (while) True: ako je random.randint (0 4) == 0: podignite Exception ('Random!') print ('Ok') my_func ()
Ovdje u konzoli možete vidjeti:
U redu Ok Ok Ok: Random!
Stvaranje vašeg dekoratera
Dekorater je funkcija unutar koje postoji druga funkcija s odgovarajućim metodama.
Primjer dekoratera u Pythonu:
def my_shiny_new_decorator (function_to_decorate):
def the_wrapper_around_the_original_function ():
print - kôd koji se pokreće do poziva funkcije ")
print (" Ja sam kôd koji radi nakon ")
vraća the_wrapper_around_the_original_function
U ovom kodu dekorater je my_shiny_new_decorator (). Kasnije dekorira function_to_decorate () iz područja parametara. the_wrapper_around_the_original_function primjer je kako će se obrađena funkcija obraditi. U ovom slučaju, dodaje se sljedeće:
print
print ("Ja sam kôd koji radi poslije")
My_shiny_new_decorator () vraća the_wrapper_around_the_original_function () na dekoraciju.
ToKako bi riješili bilo koju funkciju, okreće se dekorater.
stand_alone_function = my_shiny_new_decorator (stand_alone_function)
U ovom slučaju, funkcija je set-stand_alone_function, dekorater je my_shiny_new_decorator. Vrijednost je dodijeljena varijabli stand_alone_function.
def stand_alone_function ():
print ("Ja sam jednostavna usamljena funkcija, ne smijete me mijenjati?")
stand_alone_function ()
435]Ja sam kod koji funkcionira prije pozivanja funkcije
Ja sam jednostavna usamljena funkcija, jer me nećete usuditi promijeniti?
I ja sam kod koji radi nakon
Dakle, očito je da stand_alone_function, koja prikazuje jednu rečenicu, sada prikazuje tri rečenice. To se radi pomoću dekoratera.