Decorator е шаблон, предназначен да свързва допълнително поведение към обект. Използва се на много езици на ООП: Java, C #, PHP, JS. Python не е изключение. Задачата на декораторите може да бъде описана в следния пример. Има обект, който изпълнява някаква функция, по време на разработването на програмата трябва да добавите някаква допълнителна функционалност към нея. Тя може да бъде изпълнена преди или след, или дори по време на основните функции. За решаването на този проблем се използват декоратори. Те разширяват функционалността, премахвайки създаването на втория от същия клас с допълнителни методи. 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 ;! - fb_336x280_2 - & gt;
& lt; script & gt; (adsbygoogle = window.adsbygoogle || []). push ({});
@decorator
def retrurn_func1 ():
print new_change
Аргументи на функцията
В аргументите на декораторите на Python всеки тип данни.
Променливите от същия тип се превеждат със запетаи. Има няколко начина, по които стойностите на променливите са посочени в параметрите.
- Нормално.
- С помощта на ключови думи.
- Задачи на статичните стойности.
- Използване на позиционни елементи.
При създаване на няколко аргумента са посочени в определен ред. При извикване на параметрите всички стойности са посочени вв правилния ред.
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
Имотът е създал функциите х декоратор. Тъй като всички декоратори имат вграден сетер, методи за извличане, изтриване, можете да се обадите на един от тях.
Характеристики
При работа с декоратора трябва да вземете предвид някои от характеристиките:
- Използването на декоратори леко забавя извикването на функцията.
- След като повредена функция не може да бъде разделена. Има начини да се заобиколи това правило. Можете да създадете декоратор, който по-късно да изключите от функцията. Но това не е много добра практика.
- Поради факта, че декораторът завърта функцията, отстраняването на грешки може да бъде сложно. Проблемът е решен с помощта на модула 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, която показва едно изречение, сега показва три изречения. Това се прави с декоратора.