Python dilində dekoratorlar başqa funksiyaların davranışlarını onların özünü dəyişmədən dəyişən funksiyalardır. Bir az qəliz görünə bilər, amma misallar üzərində bunu tam anlayacağınıza əminəm.
Diqqətinizi toplayın və aşağıdakı proqram koduna nəzər yetirin:
>>> def get_text(name, sex):
if sex == "kişi":
return "cənab " + name
elif sex == "qadın":
return "xanım " + name
else:
return name
>>> def p_decorate(func):
def func_wrapper(name, sex):
return "Zati-aliləri " + func(name, sex)
return func_wrapper
>>> my_get_text = p_decorate(get_text)
>>> print(my_get_text("Lütfi Zadə","kişi"))
Zati-aliləri cənab Lütfi Zadə
>>>
Yuxarıdakı proqram kodunun əvvəlində get_text() adlı funksiya elan edilir. Bu funksiyanın təyinatı ona ötürülən arqumentlər əsasında müraciət mətnini (məsələn: cənab Lütfi Zadə) formalaşdırmaqdır. Daha sonra p_decorate() adlı bir funksiya və onun da daxilində func_wrapper() funksiyası təyin edilərək çağırılır. Burada diqqət yetirin ki, p_decorate() funksiyasına arqument kimi başqa bir funksiya ötürülür. Öz növbəsində func_wrapper() funksiyası iki arqument (name, sex) qəbul edir və onlardan p_decorate() funksiyasına arqument kimi ötürülən func funksiyası ilə istifadə edir. Dolayısıyla func_wrapper() funksiyası qaytardığı qiymət içərisində başqa bir funksiyaya müraciət edir.
Bundan sonra isə my_get_text dəyişəninə p_decorate(get_text) funksiyası mənimsədilir. Bu p_decorate(get_text) funksiyası arqument kimi başqa bir funksiyanı (get_text) qəbul edir, daxilində orijinal funksiyanın (get_text) imkanını genişləndirən yeni bir funksiyanı (func_wrapper) generasiya edir və nəticədə ümumiləşdirilmiş bir funksiyanı ərsəyə gətirmiş olur. Burada p_decorate() dekorator, get_text() isə dekorasiya olunan funksiya rolunda çıxış edir. Ən sonda isə my_get_text funksiyasına iki arqument ötürülərək ekrana çapa verilir.
Ümumiyyətlə, proqramlaşdırmada qəbul olunur ki, dekorator fərqli bir dəyişənə deyil, elə dekorasiya olunan funksiyanın özünə mənimsədilsin:
>>> get_text = p_decorate(get_text)
>>> print(get_text("Lütfi Zadə", "kişi"))
Zati-aliləri cənab Lütfi Zadə
>>>
Lakin Python dili hər hansı bir funksiyanı dekorasiya etmək üçün daha əlverişli bir üsul da təqdim edir. Dekorasiya sintaksisi adlanan bu üsul ondan ibarətdir ki, dekorator funksiyanın adı dekorasiya olunan funksiyanın təyinindən öncə @ simvolu ilə qeyd edilir:
>>> @p_decorate
def get_text(name, sex):
if sex == "kişi":
return "cənab " + name
elif sex == "qadın":
return "xanım " + name
else:
return name
>>> def p_decorate(func):
def func_wrapper(name, sex):
return "Zati-aliləri " + func(name, sex)
return func_wrapper
>>> print(get_text("Lütfi Zadə", "kişi"))
Zati-aliləri cənab Lütfi Zadə
>>>
Onu da qeyd edək ki, bir funksiya ardıcıl şəkildə bir neçə dekorator vasitəsilə dekorasiya oluna bilər. Bu zaman dekorasiya sintaksisində dekorasiya ardıcıllığının əhəmiyyət daşıdığını nəzərə almaq lazımdır.
Beləliklə, dekoratorlar arqument kimi funksiyanı qəbul edib qiymət olaraq funksiya qaytaran funksiyalardır. Proqramlaşdırmada onlar sintaktik şəkər kimi qiymətləndirilir, yəni dekoratorların tətbiqi proqramın funksionallığını artırmasa da, onun yazılmasını xeyli dərəcədə asanlaşdırır.
