17-bo‘lim
Ilg'or imkoniyatlar
Generatorlar, iteratorlar, dekoratorlar, kontekst menejerlar va comprehension'larning kengaytirilgan shakllari.
Ushbu bo‘lim mundarijasi
Bu bo'limdagi vositalar Python'ni boshqa tillardan ajratib turadi. Ular kodni qisqartiradi va xotira sarfini keskin kamaytiradi.
Comprehension - to'liq ko'rinish #
7-bo'limda ro'yxat generatorlari bilan tanishgandik. Endi to'liq imkoniyatlarini ko'ramiz.
sonlar = range(1, 11)
# Ro'yxat
kvadratlar = [son ** 2 for son in sonlar]
# Shart bilan filtrlash
juftlar = [son for son in sonlar if son % 2 == 0]
# Shartli qiymat (ternar)
belgilar = ["juft" if son % 2 == 0 else "toq" for son in sonlar]
# To'plam - takrorlar yo'qoladi
qoldiqlar = {son % 3 for son in sonlar}
# Lug'at
kublar = {son: son ** 3 for son in range(1, 6)}
print(kvadratlar)
print(juftlar)
print(belgilar[:4])
print(qoldiqlar)
print(kublar)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[2, 4, 6, 8, 10]
['toq', 'juft', 'toq', 'juft']
{0, 1, 2}
{1: 1, 2: 8, 3: 27, 4: 64, 5: 125}
Ichma-ich comprehension #
# Ikki o'lchamli jadvalni yassilash
jadval = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
yassi = [element for qator in jadval for element in qator]
print(yassi)
# Ko'paytirish jadvali
kopaytirish = [[satr * ustun for ustun in range(1, 6)] for satr in range(1, 6)]
for qator in kopaytirish:
print(qator)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5]
[2, 4, 6, 8, 10]
[3, 6, 9, 12, 15]
[4, 8, 12, 16, 20]
[5, 10, 15, 20, 25]
Generatorlar #
Generator ro'yxatga o'xshaydi, lekin elementlarni oldindan hisoblamaydi - har birini so'ralganda hosil qiladi.
import sys
royxat = [son ** 2 for son in range(1_000_000)] # kvadrat qavs
generator = (son ** 2 for son in range(1_000_000)) # dumaloq qavs
print(f"Ro'yxat: {sys.getsizeof(royxat):>10,} bayt")
print(f"Generator: {sys.getsizeof(generator):>10,} bayt")
Ro'yxat: 8,448,728 bayt
Generator: 192 bayt
yield bilan generator funksiyasi #
def fibonachchi(nechta):
"""Fibonachchi ketma-ketligini birma-bir hosil qiladi."""
oldingi, joriy = 0, 1
for _ in range(nechta):
yield oldingi
oldingi, joriy = joriy, oldingi + joriy
for son in fibonachchi(10):
print(son, end=" ")
print()
# Ro'yxatga aylantirish ham mumkin
print(list(fibonachchi(15)))
0 1 1 2 3 5 8 13 21 34
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]
return va yield farqireturn funksiyani tugatadi. yield esa qiymatni qaytaradi va funksiyani to'xtatib turadi - keyingi so'rovda o'sha joydan davom etadi. Barcha lokal o'zgaruvchilar saqlanib qoladi.
Amaliy foyda: katta fayllarni o'qish #
def log_satrlari(yol, kalit_soz):
"""Katta log faylidan faqat kerakli satrlarni birma-bir qaytaradi."""
with open(yol, "r", encoding="utf-8") as fayl:
for raqam, satr in enumerate(fayl, start=1):
if kalit_soz in satr:
yield raqam, satr.strip()
# 10 GB li faylni ham xotirani to'ldirmasdan o'qiydi
for raqam, satr in log_satrlari("xatolar.log", "ERROR"):
print(f"{raqam:>5}: {satr}")
2: 2026-09-08 14:42:03 [ERROR] Nolga bo'lishga urinish: 10 / 0
17: 2026-09-08 14:51:20 [ERROR] Fayl topilmadi: hisobot.csv
Iteratorlar #
Generator - iterator protokolining oddiy shakli. Protokolni o'zingiz ham amalga oshirishingiz mumkin:
class TeskariSanoq:
"""Berilgan sondan nolgacha teskari sanaydi."""
def __init__(self, boshlanish):
self.joriy = boshlanish
def __iter__(self):
return self
def __next__(self):
if self.joriy <= 0:
raise StopIteration
self.joriy -= 1
return self.joriy + 1
for son in TeskariSanoq(5):
print(son, end=" ")
print("Start!")
5 4 3 2 1 Start!
Dekoratorlar #
Dekorator - funksiyani o'zgartirmasdan unga qo'shimcha xatti-harakat qo'shadigan funksiya.
import time
from functools import wraps
def vaqtni_olcha(funksiya):
"""Funksiya bajarilish vaqtini o'lchaydi."""
@wraps(funksiya)
def orab_oluvchi(*args, **kwargs):
boshlanish = time.perf_counter()
natija = funksiya(*args, **kwargs)
davomiylik = time.perf_counter() - boshlanish
print(f" [{funksiya.__name__}] {davomiylik:.4f} soniya")
return natija
return orab_oluvchi
@vaqtni_olcha
def katta_yigindi(chegara):
"""Berilgan chegaragacha bo'lgan sonlar yig'indisi."""
return sum(range(chegara))
natija = katta_yigindi(5_000_000)
print(f"Natija: {natija:,}")
[katta_yigindi] 0.1284 soniya
Natija: 12,499,997,500,000
@wraps nima uchun kerak?Dekoratorsiz o'ralgan funksiyaning __name__ va docstring'i yo'qoladi - u orab_oluvchi bo'lib ko'rinadi. functools.wraps asl ma'lumotni saqlab qoladi. Dekorator yozayotganda uni doim qo'shing.
Foydali dekorator misollari #
from functools import wraps
def qayta_urin(marta=3):
"""Xato bo'lsa funksiyani belgilangan marta qayta chaqiradi."""
def dekorator(funksiya):
@wraps(funksiya)
def orab_oluvchi(*args, **kwargs):
for urinish in range(1, marta + 1):
try:
return funksiya(*args, **kwargs)
except Exception as xato:
print(f" {urinish}-urinish muvaffaqiyatsiz: {xato}")
if urinish == marta:
raise
return orab_oluvchi
return dekorator
def kirish_talab_qilinadi(funksiya):
"""Foydalanuvchi tizimga kirganini tekshiradi."""
@wraps(funksiya)
def orab_oluvchi(foydalanuvchi, *args, **kwargs):
if not foydalanuvchi.get("kirgan"):
return "Ruxsat yo'q: avval tizimga kiring"
return funksiya(foydalanuvchi, *args, **kwargs)
return orab_oluvchi
@kirish_talab_qilinadi
def maxfiy_malumot(foydalanuvchi):
return f"Salom {foydalanuvchi['ism']}, maxfiy ma'lumot: 42"
mehmon = {"ism": "Noma'lum", "kirgan": False}
egasi = {"ism": "Husanboy", "kirgan": True}
print(maxfiy_malumot(mehmon))
print(maxfiy_malumot(egasi))
Ruxsat yo'q: avval tizimga kiring
Salom Husanboy, maxfiy ma'lumot: 42
Tayyor dekoratorlar #
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonachchi(son):
"""Keshlash bilan - juda tez."""
if son < 2:
return son
return fibonachchi(son - 1) + fibonachchi(son - 2)
print(fibonachchi(50))
print(fibonachchi.cache_info())
12586269025
CacheInfo(hits=48, misses=51, maxsize=None, currsize=51)
fibonachchi(50) keshsiz taxminan 40 milliard marta chaqirilardi. @lru_cache bir marta hisoblangan natijani eslab qoladi va 51 ta chaqiruv bilan tugaydi.
| Dekorator | Vazifasi |
|---|---|
@property | Metodni atribut kabi ishlatish |
@staticmethod | Klass ichidagi mustaqil funksiya |
@classmethod | Klassning o'zi bilan ishlaydigan metod |
@lru_cache | Natijalarni keshlash |
@wraps | Dekoratorda meta-ma'lumotni saqlash |
@abstractmethod | Majburiy amalga oshiriladigan metod |
@staticmethod va @classmethod #
class Sana:
def __init__(self, kun, oy, yil):
self.kun, self.oy, self.yil = kun, oy, yil
@classmethod
def matndan(cls, matn):
"""Alternativ konstruktor: "08.09.2026" -> Sana obyekti."""
kun, oy, yil = map(int, matn.split("."))
return cls(kun, oy, yil)
@staticmethod
def kabisa_yilmi(yil):
"""Klass yoki obyektga bog'liq bo'lmagan yordamchi funksiya."""
return yil % 4 == 0 and (yil % 100 != 0 or yil % 400 == 0)
def __str__(self):
return f"{self.kun:02d}.{self.oy:02d}.{self.yil}"
sana = Sana.matndan("08.09.2026")
print(sana)
print(Sana.kabisa_yilmi(2026))
print(Sana.kabisa_yilmi(2028))
08.09.2026
False
True
Kontekst menejerlar #
with bilan ishlaydigan o'z obyektingizni yaratish:
import time
class Taymer:
"""Kod blokining bajarilish vaqtini o'lchaydi."""
def __init__(self, nomi):
self.nomi = nomi
def __enter__(self):
self.boshlanish = time.perf_counter()
print(f"[{self.nomi}] boshlandi...")
return self
def __exit__(self, xato_turi, xato_qiymati, izlar):
davomiylik = time.perf_counter() - self.boshlanish
if xato_turi is None:
print(f"[{self.nomi}] tugadi: {davomiylik:.4f} soniya")
else:
print(f"[{self.nomi}] xato bilan tugadi: {xato_qiymati}")
return False # xatoni yashirmaymiz
with Taymer("Katta hisob-kitob"):
jami = sum(son ** 2 for son in range(3_000_000))
print(f"Natija: {jami:,}")
[Katta hisob-kitob] boshlandi...
[Katta hisob-kitob] tugadi: 0.3517 soniya
Natija: 8,999,995,500,000,500,000
Yanada qisqa usul - contextlib:
from contextlib import contextmanager
import time
@contextmanager
def taymer(nomi):
boshlanish = time.perf_counter()
try:
yield
finally:
print(f"[{nomi}] {time.perf_counter() - boshlanish:.4f} soniya")
with taymer("Saralash"):
katta_royxat = sorted(range(1_000_000), reverse=True)
[Saralash] 0.0821 soniya
itertools - kuchli vositalar #
from itertools import count, cycle, chain, combinations, groupby
# Cheksiz sanoq
for son in count(10, 5):
if son > 30:
break
print(son, end=" ")
print()
# Bir nechta ro'yxatni ketma-ket aylanish
for element in chain([1, 2], ["a", "b"], (True, False)):
print(element, end=" ")
print()
# Kombinatsiyalar
jamoa = ["Husanboy", "Sardor", "Malika"]
for juftlik in combinations(jamoa, 2):
print(" - ".join(juftlik))
10 15 20 25 30
1 2 a b True False
Husanboy - Sardor
Husanboy - Malika
Sardor - Malika
tub_sonlar(chegara)generator funksiyasini yozing -yieldbilan tub sonlarni birma-bir qaytarsin.@vaqtni_olchadekoratorini yozib, uni tub sonlarni hisoblashda sinab ko'ring.@lru_cachebilan rekursiv funksiya yozing va keshsiz variant bilan tezligini solishtiring.FaylYozuvchikontekst menejerini yarating -withblokidan chiqishda faylga "Yakunlandi" deb yozsin.
Xulosa #
- Comprehension'lar ro'yxat, to'plam va lug'at uchun ishlaydi.
- Generator elementlarni talab bo'yicha hosil qiladi va xotirani tejaydi;
yieldbilan yoziladi. - Dekorator funksiyani o'zgartirmasdan unga qo'shimcha xatti-harakat qo'shadi.
@lru_cachetakroriy hisob-kitoblarni keskin tezlashtiradi.__enter__/__exit__yoki@contextmanagerbilan o'zwithblokingizni yarating.itertoolsmoduli ketma-ketliklar bilan ishlashning tayyor vositalarini beradi.
Keyingi bo'limda standart kutubxonaning eng foydali modullarini batafsil ko'rib chiqamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.