Python dekoratéři - je to co?

Decorator je šablona navržená pro připojení dalšího chování k objektu. Používá se v mnoha jazycích OOP: Java, C #, PHP, JS. Python není výjimkou. Úloha dekoratérů je popsána v následujícím příkladu. Existuje objekt, který provádí nějakou funkci, během vývoje programu je třeba přidat další funkce. Může být proveden před nebo po, nebo dokonce během hlavních funkcí. Pro vyřešení tohoto problému se používají dekorace. Rozšiřují funkcionalitu, čímž eliminují tvorbu druhé ze stejné třídy s dalšími metodami. Dektoři Pythonu jsou druh obalu, který mění chování funkce. Jako změněný objekt se používá třída, funkce nebo jiný dekorátor. Měli by být velmi opatrní a jasně pochopili, co přesně je třeba dosáhnout. Příliš mnohokrát používání dekorátorů vede ke komplikacím porozumění kódu.


Dekorátor a funkce

Dekorační prvky v Pythonu jsou funkce, která jako argument argumentují jinou funkcí. Jedná se o blok kódu, který vrací určitou hodnotu.
Obsahuje argumenty, že budou použity v budoucnu, ovlivní návratovou hodnotu. Výstupní výstup může být jakéhokoli typu: seznam, n-tice, funkce. V Pythonu je každá funkce objekt, je deklarován klíčem def. Rozsah hodnot není uveden zkrácenými závorkami, ale kartou odsazení. Klíčové slovo je následováno názvem, argumentemjsou uvedeny v závorkách () za jménem. Před přepnutím na nový řádek je umístěn symbol ":". V Pythonu nemůže být tělo prázdné, musí obsahovat seznam příkazů. Chcete-li opustit toto místo, vložte prázdný průkaz operátora.

def empty_func ():

pass

Podobná syntaxe se vztahuje na všechny funkce kromě anonymních. Anonymní je následující:

func = lambda x, y: x + y

Vydáno:

func (1, 2) # vrací 3

Call (druhá metoda)

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

na zdobení způsobena následujícím způsobem:

název @ natěrač
def yzmenyaemaya_funktsyya
yzmenyaemoy_funktsyy těla

schéma práce popsán následující kód:

def natěrač (change_funct):
def return_func1 ():
tiskové "kód, než se"
change_funct ()
print "kód po"
vratné return_func1

V souladu s tím, je volání je následující:

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

& lt; script & gt; (adsbygoogle = window.adsbygoogle || []) stisknout ({});
@decorator
def retrurn_func1 ():
pro tisk new_change

argumenty

argumentů předaných Python dekorace jakýkoliv typ data.

Proměnné stejného typu jsou překládány čárkami. Existuje několik způsobů, kterými jsou parametry proměnné zadány.

  1. Normální.
  2. Pomocí klíčových slov.
  3. Úkoly statických hodnot.
  4. Použití polohových prvků.

Při vytváření jsou v určitém pořadí zadány více argumentů. Při volání parametrů jsou zadány všechny hodnoty vve správném pořadí.

def větší (a, b):
pokud a & gt; b:
tisku a
dále:
tisku B

Správná výzva

větší, 

(66 ) Chybné volání:

větší, 

větší, (1273)

v případě, že argumenty jsou klíčová slova z výzvu náhodně, jak je používán hodnota určuje konkrétní klíč název.

def osoba (jméno, věk):
print jméno, "je", "věk", "let"
Osoba (věk = 23 name = "John")

Statické proměnné jsou vytvořeny s funkcí prostřednictvím operátor přiřazení, jako by inicializace došlo v těle.


Funkce a metody jsou syntakticky podobné.

Rozdíl je v tom, že funkce se nazývá pouze názvem.

func ()

Volání metody se provádí prostřednictvím operátora. "" a zadá se název metody, kde první parametr je nadřazený.

object.func ()

, a tím, Python malíři vytvořit metody, jakož i funkci.

Zde jsme vytvořili natěrač def method_friendly_decorator (method_to_decorate):

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

, F je vytvoření třídy s metodami, které by později byly modifikované ^

třída Lucy (objekt):
def __init __ (self )
self.age = 32

@method_friendly_decorator
def sayYourAge (self, lež):
print "? jsem% S, ale kolik dáte" % (Self.age + lež)

Lucy.sayYourAge (-32)
# 26 a dal jsem vám, co?

Zde je použitý formát (). Přiřazeno k formátovaným řetězcům, které se používají takto:


, s výjimkou K dispozici je jen jeden dekorátor, několik úrovní zábalek je realizováno. Když vytvoříteinvestoval natěrač začíná každý nový řádek, počet řádků určuje úroveň obtížnosti. Zdá se, že toto:

@AAA
@BBB
@CCC
funkce def ():
procházejí

V souladu s tím, AAA (), přijímá parametry BBB () a zpracovává CCC ().

def f ():
procházejí:
,
, f = (AAA BBB (CCC (funkce))):

Funkce prošel tři různé dekory, je přiřazen f (). Každý z nich vrátí svůj výsledek, který zase zpracovává obal. Můžete si všimnout, že posledním dekorátorem seznamu je první, spustí funkci zpracování ().

V Pythonu vypadají také dekoratéři třídy.

@firsdecorator 

@seconddecorator
,
, třída CDC:

procházejí:
,
, C = firstdecorator (seconddecorator (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'

tisku (myFunc ()) # zobrazení této "XXYYZZPython"

V tomto případě se provádění obalovou logika je pomocí def lambda:


& lt; script type = "text /javascript" & gt;
var blockSettings = {blockId: "R-A-70350-45", renderTo: "yandex_rtb_R-A-70350-45", asynchronní :! 0};
, pokud (document.cookie.indexOf ("abmatch =") větší nebo rovno 0) blockSettings.statId = 70350;
! Funkce (a, b, c, d, e) {a [c] = a [c] || [], a [c] .push (funkce () {Ya.Context.AdvManager.render (blockSettings)}), e = b.getElementsByTagName ("scénář") , d = b.createElement ("scénář"), 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 () se otáčí myFunc, ZZPython vrátí namísto předchozího řádku Python. Pak začne zvrátit FN2 (), která vrátí výsledek do konce YYZZPython. Na konci fn1 () zpracovává myfunc () aVrací konečný výsledek - řádek XXYYZZPython.

vloženého malíři

Existují vestavěných funkcí dekorace Python. Přicházejí s tlumočníkem kompletní, pro jejich použití je třeba importovat další moduly.

Staticmethod zpracovává-funkce argumentu tak, že je statická a bere spetsyfykator statické.

Třída C: 

@staticmethod

def f (arg1 arg2): #static

procházejí
(252 ) Classmethod dělá třídu se zpracovanou funkcí.

, třída MyClass: 

@classmethod
,
, metoda def (CLS, arg):
,
, pro tisk ('% s classmethod% D' % (CLS .__ name__, arg))

@classmethod

def call_original_method (CLS):

cls.method



def call_class_method (self):

self.method

třída 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

# Nazýváme metody třídy prostřednictvím objektu.

my_obj = MyClass ()

my_obj.method



my_obj.call_class_method ()

Každá funkce může být použita dekorátor

Náhradní tvůrci a hetterov

s třídy jmenován vlastnictví getry, regulátorů, deletterы.

pevnostní třídy ([fget [, FSET [, fdel [, doc]]]])

getry a zápis na stroji, jsou následující:

Provede se přenos parametrů do třídy Python. Vlastník dekorace má metody:

  • fget - získá hodnotu atributu;
  • fset definuje hodnotu atributu;
  • odstraňuje fdel;
  • doc vytvoří popis atributu. Pokud dokument neníje přiřazena, vrátí kopii popisu fget (), pokud existuje.
, třídy C (objekt): 

def __init __ (self):

self._x = Žádné

def getx (self):

vratné self._x

def SETX (self, hodnota):

self._x = hodnota

def delx (self):

del self._x

x = vlastnictví (getx, SETX, delx, "Jsem 'x' vlastnost".)

za použití dekoratér Pythonproperty:

, třídy C (objekt): 

def __init __ (self):

self._x = Žádné

@property

def x (self):
,
, "". "jsem 'x' vlastnost" ""

vratné self._x
,
, 'x.setter

def x (self, hodnota):

self._x = hodnota
,
, 'x.deleter

def x (self):

del self._x

Vlastnost vytvořila funkce x dekorátor. Vzhledem k tomu, že všichni dekoranti mají vestavěný setter, getter, deletter metody, můžete volat jeden z nich.

Funkce

Při práci s dekorátorem je třeba vzít v úvahu některé funkce:

  1. Použití dekorátorů mírně zpomaluje volání funkce.
  2. Jakmile nelze poškozenou funkci rozdělit. Existují způsoby, jak obejít toto pravidlo. Můžete vytvořit dekorátor, který můžete později odpojit od funkce. Ale to není velmi dobrá praxe.
  3. Vzhledem k tomu, že dekorátor otáčí funkci, ladění může být komplikované. Problém je řešen pomocí modulu functools.

Functools modul je sbírka metod, která poskytuje interakci s dalšími funkcemi a je také dekorátorem Pythonu.

Užitná metoda cmp_to_key (func) převádí klávesu cmp () (). Obě metody jsou pro třídění seznamu, ale první je odstraněn z Pythonu 3.0 a druhý je přidán ve verzi 2. Lru_cache ukládá poslednívolání do mezipaměti. Pokud je maxsixe zadán jako žádný, velikost mezipaměti se prodlužuje neurčitě. Slovník se používá k ukládání často používaných dotazů. Je-li argument zadán = true, argumenty různých typů jsou ukládány do mezipaměti zvlášť. Podle toho, když jsou napsány = true, jsou uloženy v jediném seznamu.

Total_ordering zdobí třídu, která obsahuje srovnávací metody, a přidá všechny ostatní.

částečnou (Func, * args **, klíčová slova) vrátí funkci, která způsobené první argument oblasti parametry metody, přenáší poziční * args, která je dána jedna, a tzv kwargs.

Snížení funguje takto:

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

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

Snížení důsledně použití úkon párů předměty uvedené v seznamu * * klíčová slova nebo všechny položky * args. Tak ve výše uvedeném příkladu použití funkce lambda ovládal první dva prvky:

1 + 2

, pak se výsledek sečtené s třetím přijatého tohoto výsledku se přidá k následujícímu prvky, atd.

Update_wrapper aktualizuje shell, aby se podobal funkci zabalené. Argumenty specifikují tyto dvě funkce, kopírované a aktualizované atributy.

, přiřazené = WRAPPER_ASSIGNMENTS

kolony WRAPPER_ASSIGNMENTS obsahuje výchozí hodnoty __name__, __module__, __annotations__ a __doc__.

aktualizované = WRAPPER_UPDATES

K WRAPPER_UPDATES uvedené atributy aktualizovány výchozí __dict__.

Obálky volaly částečně jako dekorátor.

Dekorace chyb

Možnosti dekoratérů vám umožňují vytvořit takovéFunkce, která v případě chyby dává jeden výsledek, pokud není chyba - na straně druhé.

Realizace:

dovozní functools def opakovat (func): @ functools.wraps (func) def obalu (* args, ** kwargs): zatímco True: pokusit : návrat FUNC (* args, ** kwargs) s výjimkou výjimka: průchod vratného obalu

ukazuje, že v případě funkce výjimky začíná znovu.

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

Tento kód znamená, že 9 z 11 případů, dojde k chybě.

def my_decorator (fn): def zabalené (): try: return fn () s výjimkou Exception e: print ("Chyba:", e) návrat zabalený @my_decorator def my_func (): import náhodný, zatímco pravda: pokud random.randint (0 4) == 0: zvýšit výjimka (! 'random') print ('OK') my_func ()

obdržíte konzoly:

OK OK OK Chyba: Random!

vytvořením jeho natěrač

natěrač je funkce, která se nachází v jiné funkce pomocí vhodných metod.

Příklad natěrač Python:

def my_shiny_new_decorator (function_to_decorate): 

def the_wrapper_around_the_original_function ()

pro tisk („I - kód, který je spuštěn pro funkci volání ")

function_to_decorate ()

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

return the_wrapper_around_the_original_function

v tomto kódu malíř je my_shiny_new_decorator (). Dále zdobí function_to_decorate () z parametrů pole. the_wrapper_around_the_original_function - je příkladem toho, jak má být léčen dekoryruemaya funkci. V tomto případě, který zní:

print ("I - kód, který je spuštěn pro funkci volání") 

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

My_shiny_new_decorator () vrací dekoruyemu the_wrapper_around_the_original_function ().

out libovolnou funkci, otáčí natěrač.

stand_alone_function = my_shiny_new_decorator (stand_alone_function)

V tomto případě, dekorovaný funkce - stand_alone_function, natěrač - je my_shiny_new_decorator. Hodnota přiřazená proměnné stand_alone_function.

def stand_alone_function () 

print ("Jsem prostý jediné funkce, protože nemáte posmeesh změním?")

stand_alone_function ()
I - kód pro spuštění pro volání funkce 

jsem jednoduchý single funkce, protože nemáte posmeesh změním?

I - kód, který se spustí po


Je tedy jasné, že stand_alone_function, který podrážděný obrazovky jednu větu, se nyní zobrazuje tři návrhy. To se provádí pomocí natěrač.

Související publikace