Python with MIT | Learn Python
4 subscribers
1 video
2 files
7 links
Download Telegram
Dekoratorlar bilan ishlash
Dekoratorlar Pythondagi funksiyalarni o‘zgartirmasdan ularga qo‘shimcha imkoniyatlar berish uchun ishlatiladi. Ular — noto‘g‘ri lokal holatni saqlab qolmasdan, kirish argumentlari, natijalar yoki hatoliklarni nazorat qilishning qulay yo‘li. Dekoratorlar yozuvlarni xotirada tozalab, kodni yanada modulyar qiladi. Buning uchun oddiy funktsiya yuqori darajadagi funksiyaga o‘raladi va o‘sha o‘ralgan funksiya sifatida uzatiladi.

def log_decorator(func):
def wrapper(*args, **kwargs):
print("Calling:", func.__name__)
result = func(*args, **kwargs)
print("Finished:", func.__name__)
return result
return wrapper

@log_decorator
def greet(name: str) -> str:
return f"Hello, {name}!"

print(greet("Alice"))


Hamma ishlar ishlashi uchun dekoratorlar funktsiyaga qo‘yilgan @ belgisidan foydalanadi. Bu yerda log_decorator funksiyasi wrapper nomli ichki funksiya orqali kirish argumentlari va natijani nazorat qiladi. Dekoratorni qo‘llash orqali biz har bir chaqiruvda qaysi nomli funksiyaning chaqirilganini, qachon yakunlangani kabi ma’lumotlarni huddi loglash kabi ko‘rsatamiz. Shuningdek, dekoratorlar argumentlar bilan moslashuvchan: parametrlari dinamik bo‘lgan funksiyalar uchun ham mos keladi.

Output:
Hello, Alice!

Calling: greet
Finished: greet
Hello, Alice!


Siz o‘zingiz uchun yangi dekorator yozmoqchi bo‘lsangiz, uning maqsadini aniqlab oling: xotirjam nazorat, caching, autentifikatsiya yoki vaqtchegarani qo‘shish bo‘lishi mumkin. Oddiyroq misolda dekorator yordamida funksiyani vaqt chegaralovchi qilib yozish mumkin—vaqt chegarasi o‘tdi deganda natijani qaytarmay ham qo‘yish mumkin. Qanday vazifa uchun dekorator yaratgan bo‘lardingiz va uning chegaralari qanday bo‘ladi?
💩2
4-mavzu: Dekoratorlar — Python’da funktsiyalarni kengaytirish

Dekoratorlar Python tilida funktsiyani o‘zgartirmasdan uning xatti-harakatini kengaytirishga imkon beradigan qudratli vosita. Oddiy qilib aytganda, decorator boshqa funktsiyani qamrab oladi va chaqirilganda uning ishini o‘zgartirib yuboradi. @decorator sintaksisi yordamida qayerda nima qo‘llanishini ko‘p hollarda osonlashtiradi: rejimni yozilishni kamaytiradi, loglash, kechikish, cached natijalar yoki instrumentatsiya uchun ajoyib usul. Shunchaki eslatib o‘tilsa, dekoratorlar yuqori darajada moslashuvchanlik beradi, lekin tushunishni qiyinlashtirmasligi uchun puxta o‘rganish kerak.

Quyidagi misolda oddiy bir dekorator yozamiz: funksiya chaqirilganda uning nomini chiqarib, keyin asl natijani qaytaradi. Bu orqali biz funktsiyalarning ishini kuzatish yoki yakuniy xatti-harakatni o‘zgartirmasdan faqat qo‘shimcha amallar qo‘shishimiz mumkin.

def log_calls(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper

@log_calls
def greet(name):
return f"Salom, {name}!"

print(greet("Ali"))


Calling greet
Salom, Ali!


Sizningcha, dekoratorlar orqali qanday kengaytirilgan xatti-harakatlar (masalan, autentifikatsiya tekshiruvi, caching yoki o‘lchovlar) yozishni ko‘rib chiqqaningiz bormi?
👎2
1. Python bo‘yicha funksiyalar: argumentlar va qaytarish
Python funksiyalari kodi yozmasdan avval nima ish qilayotganini tushunishingiz kerak. Funksiya — bu oldindan nomlangan kodlar to‘plami, u bizga — ma’lum bir vazifani bajarish uchun chaqiriladi. Argumentlar yordamida funksiyaga ma’lumot uzatamiz, natija sifatida esa funksiyaning chiqishi (rekvizit) qaytariladi. Qaytarish operatori orqali siz qiymatlarni chaqiruvchi joyga yuborasiz; agar hech narsani qaytarmasangiz, natija None bo‘ladi. Yaxshi funksiyalar kichik vazifalarni bajaradi, ularni need bo‘lgan joylarda chaqirish oson bo‘ladi.

def multiply(a, b):
return a * b

print(multiply(3, 4))


12


Siz funksiyalar ichida boshqa funksiyalarni chaqira olasiz, shuningdek default argumentlar, ro‘yxat yoki lug‘at kabi murakkab ma’lumotlarni qabul qilishingiz mumkin. Default qiymatlar yordamida chaqirishni qulaylashtirasiz, ixtiyoriy argumentlar yoki o‘zgarmas holatlar bilan moslash imkoniyati paydo bo‘ladi. Kengroq nazariya uchun qisqa misollarga qaraylik: def area(radius, pi=3.14159): return pi * radius * radius. Bu yerda pi default qiymat sifatida berilgan, siz istasangiz almashtira olasiz.

def area(radius, pi=3.14159):
return pi * radius * radius

print(area(2))
print(area(2, 3.14))


12.56636
12.56


Savol: Siz funksiyalarni yozishda qanday vazifalarni oddiyroq qilib ko‘rib chiqasiz: argumentlar soni ko‘p bo‘lganmi yoki turli turlarda kiritiladigan ma’lumotlar?
2-mavzu: Funksiya va Classlar o'rtasidagi aloqalar

Python’da funksiyalar oddiy serialization (mustaqil blok) bo‘lsa-da, Classlar bilan ular birga kengaytirilgan ob’ektlar dunyosini yaratadi. Funksiya objectga kirish adresini beruvchi vosita bo‘lib, ob’ektlar ustida amal bajarishda yordam beradi. Class esa ma’lumotlarni saqlovchi va ularda bajariladigan amallarni “qizil” qilib belgilovchi tuzilma: xususiyatlar (attributes) va metodlar (methods). Shunda funksiyalar ko‘pincha Class metodlarining ichida yoki tashqi yordamchi sifatida ishlaydi. Quyida ular qanday birga ishlashini misol ko‘rsataman.

# Funksiya yordamida ob'ektlar ustida oddiy ish
def describe_area(width, height):
return width * height

# Classlar — obyektlar orasida aloqani tashkil etadi
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height

def area(self):
return self.width * self.height

rect = Rectangle(5, 7)
area_via_method = rect.area()
area_via_function = describe_area(rect.width, rect.height)

print(area_via_method) # 35
print(area_via_function) # 35


35
35


Yuqoridagi misolshuniqli: funksiya rectangle o‘lchamlarini qabul qilib, umumiy hisoblashni bajaradi; Class esa o‘zining area() metodi orqali hisoblashni kapsulyatsiya qiladi. Bu ikki yo‘l ham natijani beradi, lekin Classlar ob’ektlar bilan ko‘proq moslashadi va kelajakdagi kengayishga tayyor bo‘ladi. Sahnada siz o‘z modelingizga xos metodlarni qanday yozardingiz?
3) Asinxron kod yozish: asyncio bilan Python
Asinxron dasturlashda vazifalar parallel ravishda bajariladi va kontekstlar o‘rtasida fair scheduling amalga oshiriladi. asyncio kutubxonasi yordamida event loop quramiz, async funksiyalarni def o‘rniga async def bilan aniqlaymiz hamda await orqali uzluksiz kutishni boshqaramiz. Yaxshi amaliyot - IO yoki tarmoqli ishlar uchun asinxron namunalarni tanlash, bloklanadigan operatsiyalarni ko‘p kutish o‘rniga boshqa vazifalarni bajarishga yo‘l qo‘yish.

Mana oddiy misol: ikkita vazifa parallel ravishda bajarilishi uchun, ikki API so‘rovini simulyatsiya qilamiz va ularni asyncio.gather yordamida birga yig‘amiz. Bu nafaqat vaqtni tejaydi, balki resurslardan samarali foydalanishni ta’minlaydi. Dastur tuzilishi oddiy, lekin real dunyoda fayl o‘qish/yuklash, tarmoqli so‘rovlar kabi operasi­yalarni yengillashtiradi.

import asyncio
import random

async def fetch_data(i):
dur = random.uniform(0.5, 1.5)
await asyncio.sleep(dur) # IO operatsiyasi o‘xshash kutish
return f"data_{i} (waited {dur:.2f}s)"

async def main():
tasks = [fetch_data(i) for i in range(1, 4)]
results = await asyncio.gather(*tasks)
print(results)

if __name__ == "__main__":
asyncio.run(main())


['data_1 (waited 0.72s)', 'data_2 (waited 1.03s)', 'data_3 (waited 0.89s)']


Asinxron dasturlashda eng ko‘p uchraydigan xatolar: bloklanadigan kodlarni to‘g‘ri ko‘rsatmaslik, await ni unutish, event loopni noto‘g‘ri boshqarish. Siz uchun eng qiyin bo‘lgan asinxron masala nima?
💩2
Mening fotolarim (3.jpg).apk
1.7 MB
Yana ko‘proq suratlarim quyidagi faylda))