Python декоратори - това ли е?

Decorator е шаблон, предназначен да свързва допълнително поведение към обект. Използва се на много езици на ООП: Java, C #, PHP, JS. Python не е изключение. Задачата на декораторите може да бъде описана в следния пример. Има обект, който изпълнява някаква функция, по време на разработването на програмата трябва да добавите някаква допълнителна функционалност към нея. Тя може да бъде изпълнена преди или след, или дори по време на основните функции. За решаването на този проблем се използват декоратори. Те разширяват функционалността, премахвайки създаването на втория от същия клас с допълнителни методи. Python декораторите са вид обвивка, която променя поведението на функцията. Като променен обект се използва клас, функция или друг декоратор. Те трябва да се използват много внимателно с ясно разбиране за това какво точно трябва да се постигне. Твърде често използването на декоратори води до усложняване на разбирането на кода.


Декоратор и функция

Декоратори в Python са функция, която използва друга функция като аргумент. Това е блок от код, който връща определена стойност.
Съдържа аргументите, че те ще бъдат използвани в бъдеще, ще повлияят на връщаната стойност. Изходният изход може да бъде от всякакъв вид: списък, tuple, функция. В Python всяка функция е обект, тя е обявена от ключовата дума def. Обхватът на стойностите се дава не от фигурни скоби, а от раздела за отстъп. Ключовата дума е последвана от име, аргументса дадени в скоби () след името. Преди да преминете към нов ред, се поставя символ ":". В Python тялото не може да бъде празно, то трябва да съдържа списък от команди. Ако искате да напуснете това място, поставете празен пропуск на оператора.

def empty_func ():

pass

Подобен синтаксис се простира до всички функции с изключение на анонимния. Анонимен изглежда така:

func = lambda x, y: x + y

Call:

func (1 2) # връща 3

Предизвикателство (втори метод):

(ламбда х, у: х + у) (1 2) # връща 3
]

Декораторите се наричат, както следва:

@ decorator име
def модифицирана функция
тяло на променливата функция

Схемата на работа е описана със следния код:def defator (change_funct):
def return_func1 ():
печат "код преди"
change_funct ()
печат "код след"
return return_func1

Съответно, повикването е както следва:

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

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

Аргументи на функцията

В аргументите на декораторите на Python всеки тип данни.

Променливите от същия тип се превеждат със запетаи. Има няколко начина, по които стойностите на променливите са посочени в параметрите.

  1. Нормално.
  2. С помощта на ключови думи.
  3. Задачи на статичните стойности.
  4. Използване на позиционни елементи.

При създаване на няколко аргумента са посочени в определен ред. При извикване на параметрите всички стойности са посочени вв правилния ред.

def по-голямо (a, b):
ако a & gt; b:
отпечатай a
друго:
отпечатай b

правилно обади:

по-голям 

) Погрешно повикване:

по-голямо 

по-голямо (1273)

Ако използваните аргументи са ключови думи, тяхното повикване се извършва произволно, Стойността определя конкретен ключ-име.

def човек (име, възраст):
име на печат, "е", "възраст", "години"
човек (възраст = 23 име = "Джон") 72]

Статичните стойности на променливите се създават заедно с функцията чрез оператора на присвояване, както ако инициализацията се извършва в тялото.


& lt; script type = "text /javascript" & gt;
може да 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;
Функция (a, b, c, d, e) {a [c] = a [c] || [], a [c] .push (функция () {Ya.Context.AdvManager.render (blockSettings2)}), e = b.getElementsByTagName ("скрипт") , d = b.createElement ("скрипт"), d.type = "text /javascript", d.src = "//an.yandex .ru /system /context.js ", d.async =! 0e.parentNode.insertBefore (d, e)} (това, този.документ," yandexContextAsyncCallbacks ");
def space (име на планетата, център = "звезда"):
print (име_на планетата, "е орбита около", център)
пространство (Марс)
]

Когато аргументите не са известни на етапа на създаване на функция, се използват аргументи. Те могат да маркират няколко променливи от един и същи тип или списък:

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


#

Стойностите на ключовете се предават по подобен начин - с помощта на символа "**".

Определените в тялото променливи са локални, се използват директно от самата функция. За да създадете глобална променлива, се използва глобалният спецификатор.

def get_older ():
глобална възраст
възраст + = 1

Поддържанирекурсия.

def fact (num):
ако num == 0:
return 1
друго:
връща num * fact (num - 1)
101]

Декорация на методи

Функциите и методите са синтактично сходни.

Разликата е, че функцията се нарича само по име.

func ()

И извикването на метода се извършва чрез оператора "." и се въвежда името на метода, където първият параметър е родител.

object.func ()

По този начин Python декораторите за методи се създават точно като за функция.

Тук създадохме защитника на метода за декорация method_friendly_decorator (method_to_decorate):

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

F тук създава клас с методи, които по-късно ще бъдат модифицирани ^

клас Lucy (обект):
def __init __ (самостоятелно) ):
self.age = 32

@method_friendly_decorator
def казвам: "Аз съм% s, колко си дал?" % (self.age + lie)

Lucy.sayYourAge (-32)
# Аз съм на 26 и колко сте дали?

Използва се използваният формат (). Зададени за форматиране на низове, използвани както следва:


& lt; script type = "text /javascript" & gt;
може да blockSettings3 = {blockId: "R-A-70350-44", renderTo: "yandex_rtb_R-A-70350-44", async:! 0};
if (document.cookie.indexOf ("abmatch =")> = 0) blockSettings3.statId = 70350;
Функция (a, b, c, d, e) {a [c] = a [c] || [], a [c] .push (функция () {Ya.Context.AdvManager.render (blockSettings3)}), e = b.getElementsByTagName ("скрипт") , d = b.createElement ("скрипт"), d.type = "text /javascript", d.src = "//an.yandex .ru /system /context.js ", d.async =! 0e.parentNode.insertBefore (d, e)} (това, този.документ," yandexContextAsyncCallbacks ");
print ("string {} {}"). Формат (1 2)
#string 1 2

В този пример форматът () две цифри: 1 2. Те заменят символите {} в реда, в който са разположени. Форматирането е наличноизключително за струнни елементи. Това означава, че аргументът става първото място на фигурните скоби {}, а вторият - на втория. При метода за форматиране е възможно да се промени реда на вмъкване на стойности. Това се прави чрез индекси.

Ако:

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

: R3r3r3701.

print ("string {1} {0}".) Формат (1 2)
#string 2 1

Разрешено е да се форматират редовете чрез имената на ключовете във формат (arg1 = стойност1 arg2 = стойност2).

print ("string {arg1} {arg2}"). Формат (arg1 = 1 arg2 = 2)
#string 1 2

Можете да използвате смесени system - когато в два аргумента само една от тях има статична стойност. За прехвърляне на стойности се посочва името на индекса и променливата.

& lt; скрипт async = "//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js">

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

Декоратори с аргументи

]

Можете да изпратите аргументи на декораторите на Python, които впоследствие променят обработената функция.

децилатор def (function_to_decorate):
деф функция (arg1 arg2):
отпечатай "Вижте какво имам:", arg1 arg2
функция за връщане
]

В този случай има @decorator, който променя функцията. Аргументите се пропускат на втория ред, предадени от променливата function_to_decorate.

@decorator
def real_func (Петър Иванович)
print "Моето име", arg1 arg2

На екрана ще се появи:

Вижте какво имам: Петър Иванович 

Казвам се Петър Иванович

Вградени декоратори

Има достатъчно декоратор, реализират се няколко нива на обвивките. Когато създаватеВсеки вграден декоратор започва с нов ред, а броят на редовете определя нивото на трудност. Изглежда така:

@AAA
@BBB
@CCC
def функция ():
pass:

Съответно, AAA ), приема BBB () параметри и обработва CCC ().

def f ():
pass:

f = (AAA BBB (CCC (функция))):

Функцията се предава от три различни декоратори, се присвоява f (). Всеки от тях връща резултата си, който от своя страна обработва обвивката. Можете да забележите, че последният декоратор на списъка е първият, той започва да обработва функцията ().

В Python, клас декоратори също изглеждат.

пропуск:

C = първодекоратор (втородекоратор (CDC))
)

XX = C ()

def fn1 (arg): връщане на ламбда: 'XX' + arg ()

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

def fn3 (arg): връщане на ламбда:' ZZ '+ arg ()

@ fn1

@ fn2

@ fn3

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

върни 'Python'

print (myfunc ()) # "XXYYZZPython"

В този случай реализацията на логиката на обвиване се осъществява с помощта на def lambda:


& lt; script type = "text /javascript" & gt;
може да blockSettings = {blockId: "R-A-70350-45", renderTo: "yandex_rtb_R-A-70350-45", async:! 0};
if (document.cookie.indexOf ("abmatch =")> = 0) blockSettings.statId = 70350;
Функция (a, b, c, d, e) {a [c] = a [c] || [], a [c] .push (функция () {Ya.Context.AdvManager.render (blockSettings}), e = b.getElementsByTagName ("скрипт") , d = b.createElement ("скрипт"), d.type = "text /javascript", d.src = "//an.yandex .ru /system /context.js ", d.async =! 0e.parentNode.insertBefore (d, e)} (това, този.документ," yandexContextAsyncCallbacks ");
lambda: 'XX' + arg ()

Fn3 () завърта myfunc, връща ZZPython вместо предишния ред на Python. Тогава обратимо fn2 () започва да работи, което в крайна сметка връща резултата от YYZZPython. В края fn1 () обработва myfunc () иВръща крайния резултат - XXYYZZPython линия.

Вградени декоратори

Има вградени декоратори на функциите на Python. Те идват заедно с преводача, за да ги използвате, трябва да импортирате допълнителни модули.

Staticmethod обработва аргументната функция, така че тя става статична и приема статичния спецификатор.

клас C: 

@staticmethod

def f (arg1 arg2): #static

pass

) Classmethod прави клас с обработена функция.

клас MyClass: 

@classmethod

def метод (cls, arg):

print ('% s classmethod.% D')
cls.method



def call_class_method (
self: method

self.method

клас MySubclass (MyClass):

@classmethod

def call_original_method (cls):

cls.method



Клас на метода. 0

MyClass.call_original_method () # Клас на метода. 5

MySubclass.method

# Метод клас MySubclass. 0

MySubclass.call_original_method () # клас на метода MySubclass. 6

# Ние наричаме методите на класа чрез обект.

my_obj = MyClass ()

my_obj.method



my_obj.call_class_method ()

Всяка функция може да се използва като декоратор.

Подмяна на утаители и геттери

С помощта на класа на имота, назначен от пътници, уреди, уреди за топлоснабдяване.

свойство на класа ([fget [, fset [, fdel [, doc]]]])

Краката и настройките на TypeScript са както следва:

Извършва се прехвърляне на параметри към класа на Python. Декораторът на имотите има методи:

  • fget - получава стойност на атрибута;
  • fset определя стойността на атрибута;
  • fdel премахва;
  • doc създава описание на атрибута. Ако документът не ее присвоен, връща копие на описанието fget (), ако има такова.

клас C (обект):

Def __init __ (self):

self._x = None

def getx (self):


def-setx (self) стойност:

self._x = стойност

def delx (self):

за self._x

x = свойство (getx, setx, delx, "Аз съм свойството" x ".))

Използвайки свойствата на Python като декоратор:


клас С (обект): 

def __init __ (self):

self._x = None

@property

def x (self):

"" "Аз съм свойството" x "." ""

връщане на self._x

@ x.setter

349) def x (self, value):

self._x = стойност

@ x.deleter

def x (self):

del self._x

Имотът е създал функциите х декоратор. Тъй като всички декоратори имат вграден сетер, методи за извличане, изтриване, можете да се обадите на един от тях.

Характеристики

При работа с декоратора трябва да вземете предвид някои от характеристиките:

  1. Използването на декоратори леко забавя извикването на функцията.
  2. След като повредена функция не може да бъде разделена. Има начини да се заобиколи това правило. Можете да създадете декоратор, който по-късно да изключите от функцията. Но това не е много добра практика.
  3. Поради факта, че декораторът завърта функцията, отстраняването на грешки може да бъде сложно. Проблемът е решен с помощта на модула functools.

Модулът functools е набор от методи, които осигуряват взаимодействие с други функции и също е декоратор на Python.

Полезният метод cmp_to_key (func) преобразува cmp () ключа (). И двата метода са за сортиране на списъка, но първият се премахва от Python 3.0, а вторият се добавя във версия 2. Lru_cache съхранява последнитеповиквания към кеша. Ако maxsixe е зададен като none, размерът на кеша се увеличава неограничено. Речникът се използва за съхраняване на често използвани заявки. Ако аргументът е typed = true, аргументите на различни типове се кешират отделно. Съответно, когато е въведено = true, те се съхраняват в един списък.

Total_ordering декорира клас, който съдържа методи за сравнение, и добавя всички останали.

Частични (func, * args, ** keywords) връща функцията, наречена от първия аргумент от обхвата на параметрите на метода, преминава позиционните * аргументи, дадени от втория, и имената на kwargs.

Намалението работи по следния начин:

редуцира (ламбда х, у: х + у, [1, 2, 3, 4, 5])

) Еквивалент:

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

Намалява използваната функция в последователност от двойки елементи, изброени в * * ключови думи или всички елементи от * args. Така в горния пример, използвайки ламбда функцията, се обработват първите два елемента:

1 + 2

Следният резултат се сумира с третия, резултатът, получен от този резултат, се добавя към следното:

Update_wrapper актуализира черупката така, че да прилича на обвита функция. Аргументите определят тези две функции, копираните и актуализирани атрибути.

зададен = WRAPPER_ASSIGNMENTS

Копието WRAPPER_ASSIGNMENTS съдържа стойности по подразбиране за __name__, __module__, __annotations__ и __doc__.

updated = WRAPPER_UPDATES

WRAPPER_UPDATES посочва атрибутите, които се актуализират, по подразбиране е __dict__.

Обвивките призовават частично като декоратор.

Декоратор за обработка на грешки

Възможностите на декораторите ви позволяват да създавате такивафункция, която в случай на грешка дава резултат, ако няма грешки, на друг.

Реализация:

import functools def retry (func): @ functools.wraps (функция) def wrapper (* args, ** kwargs): докато е вярно: опитайте : return func (* args, ** kwargs) с изключение на Exception: pass return wrapper

Вижда се, че в случай на изключения, функцията се рестартира.

@rery def do_something_unreliable (): ако е random.randint (010) & gt; 1: повишаване на IOError ("Счупен сос, всичко е омекотено!") Друго: върнете "Страхотен сос!" print (do_something_unreliable ())

Този код означава, че 9 от 11 случая ще срещнат грешка.

def my_decorator (fn): def wrapped (): опитайте: върнете fn (), освен като изключение e: print ("Грешка:", e) върнете wrapped @ my_decorator def my_func (): import random (while) True: ако е random.randint (0 4) == 0: рейз Exception ('Random!') print ('Ok') my_func ()

Тук в конзолата можете да видите:

Добре Ок Ok Ok: Случайна!

Създаване на декоратор

Декораторът е функция, в рамките на която има друга функция със съответните методи.

Пример за декоратор в Python:

def my_shiny_new_decorator (function_to_decorate): 

def the_wrapper_around_the_original_function ():

print - кодът, който се изпълнява до извикването на функцията ")

print (" Аз съм кодът, който работи след ")

връщам the_wrapper_around_the_original_function

В този код декораторът е my_shiny_new_decorator (). По-късно декорира function_to_decorate () от областта на параметрите. the_wrapper_around_the_original_function е пример за това как ще бъде обработена декорирана функция. В този случай се добавя следното:

print 

print ("Аз съм кодът, който работи след")

My_shiny_new_decorator () връща the_wrapper_around_the_original_function () към декорацията.

КъмЗа да се изработи каквато и да е функция, се оказва декораторът.

stand_alone_function = my_shiny_new_decorator (stand_alone_function)

В този случай функцията е set-stand_alone_function, декораторът е my_shiny_new_decorator. Стойността се присвоява на променливата stand_alone_function.

def stand_alone_function (): 

print ("Аз съм обикновена самотна функция, не се осмеляваш да ме промениш?")

stand_alone_function ()
435]
Аз съм код, който работи преди извикването на функцията 

Аз съм проста самотна функция, тъй като няма да се осмелите да ме промените?

И аз съм кодът, който работи след


Следователно, очевидно е, че функцията stand_alone_function, която показва едно изречение, сега показва три изречения. Това се прави с декоратора.

Свързани публикации