Dekoratorlar - parametrlar bilan ishlash

Dekoratorlar - parametrlar bilan ishlash

Future Dreams
Har ehtimolga qarshi: bu mavzuni yaxshiroq tushunish uchun dekoratorlar haqidagi 1-maqolani o'qishni tavsiya qilaman:  Pythonda dekoratorlar
"List comprehension"dan bexabar bo'lsangiz, mana bu maqolani o'qib chiqing: List comprehension - bu nima?

Decorator - funksiyani o'rovchi boshqa bir funksiya. Vazifasi ozgina farq qiluvchi boshqa bir dekorator yozish o'rniga, shu dekoratorni har ikkala vazifaga moslashtirish ham mumkin. Parametrlar berish orqali.

Deylik, bizda juda ko'plab funksiyalarimiz bor, ayrimlari faqat string qabul qilib, ular ustida ishlaydi. Biror joyda adashib boshqa tur berib qo'ysak, ahvol rasvo. Keling hozir bir dekorator yozamiz, u funksiyaga beriladigan hamma argumentlarni stringga aylantirib beradi.

def string(asl_funksiya):
def natijaviy_funksiya(*args, **kwargs):
args = [str(arg) for arg in args]
    kwargs = {key: str(value) for key, value in kwargs.items()}
    return asl_funksiya(*args, **kwargs)
return natijaviy_funksiya

Funksiya sodda: args va kwargs tarkibida keladigan hamma qiymatlarni stringga o'girib, keyin uni asl funksiyaga uzatdik va natijani oldik. Sinab ko'ramiz:

@string
def salom(ism):
print("Salom " + ism)
salom(42)
>>> Salom 42

Funksiyaga integer qiymati argument qilib berdik, u esa xatosiz ishladi. Maqsadga yetdik. Bizda endi navbatdagi muammo bor, deb tasavvur qiling: ba'zida funksiyaga string beramiz, lekin uning boshida yoki oxirida keraksiz probellar bo'ladi, biz ulardan xalos bo'lishimiz kerak, lekin faqatgina biz xohlagan paytimizda bu ishni qilamiz. Tepadagi dekoratorga qo'shimcha parametr bersak, deylik, clear degan. Unga True berganimizda tozalasin, aks holda tozalamasin.

@string(clear=True)
def salom(ism):
print("Salom " + ism)
salom(" Ali ")
>>> Salom Ali

Natija yomonmas, ortiqcha probellar o'chirildi. Endi ishga o'tamiz, qanday qilamiz buni?

Eng avval bir narsani tushunishimiz kerak. @string va @string() bu ikkalasi ikki xil dekorator. Shunchaki oddiy ilonshunosning ko'zi bilan qarang: birida shunchaki funksiya obyekti edi, ikkinchisida esa o'sha funksiya chaqirilgan () orqali. Demak, biz string funksiyasi chaqirilganda, u dekorator qaytaradigan qilishimiz kerak. Tushunmadingizmi? Xo'p, musiqani o'chirib qo'yib yaxshiroq e'tibor bering.

@string() qilingan paytda, string() qilingandagidek funksiya chaqiriladi, bu funksiya endi bizga dekorator qaytarishi kerak.

Parametrli dekoratorning ishlashi

G'oyani tushungan bo'lsangiz, bitta narsa siz uchun aniq bo'ladi endi: string funksiyasi ichida endi biz dekoratorni qayta yozishimiz kerak va uni natija sifatida qaytarishimiz kerak.

def string(clear=False):
def dekorator(asl_funksiya):
def f(*args, ***kwargs):
args = [
            str(arg).strip() if clear else str(arg)
            for arg in args
           ]
      kwargs = {
            key: str(value).strip() if clear else str(value)
            for key, value in kwargs.items()
            }
     return asl_funksiya(*args, **kwargs)
return f
return dekorator

Xo'sh, hammasi hozirgina o'ylab chalkashib ketgan xayollaringizda o'ylaganingizdek murakkab emas. Bu shunchaki oddiy funksiya, faqat ozroq qo'shimcha bosqichlar bilan. Demak, butun diqqatni f funksiyasiga qarating - bu dekoratorimiz qaytarishi kerak bo'lgan, yakuniy funksiya. Biz uni ishlatamiz. Uning ichiga e'tibor bering: shunchaki list comprehension yordamida har bir argumentni stringga aylantiryapmiz, yo'l-yo'lakay clear parametrini tekshirib, u True bo'lgan holda strip() funksiyasi orqali bosh va oxiridagi probellarni o'chirib ketyapmiz. Eng oxirida shu argumentlarni asl_funksiya funskiyasiga beryapmiz va u qaytargan natijani qaytaryapmiz. asl_funksiya - bu biz qayta ishlashimiz kerak bo'lgan funksiya (hozirgi holatimizda salom funksiyasi).

Endi bir qadam tashqariga chiqamiz: dekorator funksiyasi - bu bizdagi haqiqiy dekorator funksiya. string() chaqirilganda shu funksiya obyekti qaytariladi, aynan u funksiyani qayta ishlovchi boshqa bir funksiyadir.

Vaziyat soddalashib, tumanlar tarqab boshladi. Yoki haliyam hech nima tushunarsizmi? Unda tepaga chiqib qaytadan o'qib ko'ring.

Sezgan bo'lsangiz, shunchaki dekorator ichida odatda bitta funksiya bo'lar edi, endi biz ularni 2 ta qildik. Yana bir qavat bilan o'rab qo'ydik, chunki parametr berish uchun funksiya nomiga qavs qo'yganimizda u o'sha zahoti ishga tushadi va o'sha ishga tushgan funksiya endi yo'q, o'z ishini bajarib, o'yindan chiqadi, endi dekorator vazifasini uning ichidagi funksiya bajarib boshlaydi (bizning holatimizda dekorator funksiyasi). Shunda ichkarida odatdagidek 1 ta funksiya (f funksiyasi) qoladi, xolos.

@string() dekoratorini endi @string shaklida ishlataversam bo'ladimi? Yo'q. Parametrli funksiyani parametrsiz o'rnida ishlatish mumkin emas. Bu siz xohlamagan rasvogarchilikka sabab bo'ladi.

Nimalardir tushunarsiz bo'ldi-a? Marhamat qilib qaytadan o'qing. Maqolani o'qish bu nazariya. Haqiqiy bilim amaliyotda olinadi. Bularni hozir o'tirib sinab ko'ring. Maqolada yozmagan narsalarimni kashf qilishingiz mumkin.

Savollarni @python_uz guruhiga yozing.

Report Page