Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Quvur tuzilishi
- 2.2. Elementlar qanday oqadi
- 2.3. Bosqich turlari: funksiya yoki ifoda
- 2.4. itertools — tayyor bosqichlar
- 2.5. groupby tuzog'i
- 2.6. tee tuzog'i
- 2.7. Quvurdagi xatolar
- 2.8. Qachon generator kerak emas
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Quvurda elementlar qanday oqadi
- Misol 2 — itertools bilan generatorlar va ularning tuzoqlari
- Misol 3 — Retseptlar kutubxonasi
- Misol 4 — Amaliy: bir nechta filialdan oqimli sotuv hisoboti
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
10.4-dars: Generator amaliyoti
10-QISM — ILG'OR TIL IMKONIYATLARI · 4-dars
1. Kirish va motivatsiya
Tasavvur qiling: har kuni 20 GB lik veb-server logi keladi. Vazifa — oxirgi soatdagi 500 xatolarning eng sekin 10 tasini topish.
Birinchi urinish:
qatorlar = open("access.log").readlines() # ⚠️ 20 GB xotiraga
yozuvlar = [tahlil(q) for q in qatorlar] # ⚠️ yana 20+ GB
xatolar = [y for y in yozuvlar if y.kod == 500]
eng_sekin = sorted(xatolar, key=lambda y: y.vaqt)[-10:]Kompyuter xotirasi tugaydi va dastur yiqiladi.
Generatorlar bilan:
qatorlar = open("access.log") # qatorma-qator
yozuvlar = (tahlil(q) for q in qatorlar)
xatolar = (y for y in yozuvlar if y.kod == 500)
eng_sekin = heapq.nlargest(10, xatolar, key=lambda y: y.vaqt)Xuddi o'sha mantiq, lekin xotirada bir vaqtning o'zida bitta qator va 10 ta natija turadi. Fayl 20 GB bo'ladimi, 200 GB mi — farqi yo'q.
Bu naqsh — generator quvuri (pipeline). U Unix'dagi cat access.log | grep 500 | sort | head ning Python'dagi ekvivalenti: har bosqich oldingisidan element oladi, qayta ishlaydi va keyingisiga uzatadi.
O'tgan darsda generator qanday ishlashini o'rgandik. Bu darsda ular bilan qanday ishlashni o'rganamiz.
Bu darsda:
- Generator quvurlari: manba → bosqichlar → yakunlovchi
- Quvurda elementlar qanday "oqadi"
itertoolsbilan generatorlar- Tayyor retseptlar: bo'laklash, siljuvchi oyna, takrorsiz, birlashtirish
-
teevagroupbytuzoqlari - Quvurda xatolar bilan ishlash
- Qachon generator kerak emas
2. Nazariya — chuqur tushuntirish
2.1. Quvur tuzilishi
Har quvur uch turdagi bosqichdan tashkil topadi:
| Bosqich | Nima qiladi | Misol |
|---|---|---|
| Manba | Elementlarni ishlab chiqaradi | fayl, range, API, count() |
| Oraliq | Element oladi, element beradi | filtr, o'zgartirish, tahlil |
| Yakunlovchi | Hammasini iste'mol qiladi | sum, list, max, for, fayl yozish |
def qatorlar(yol): # manba
with open(yol, encoding="utf-8") as f:
yield from f
def tozala(oqim): # oraliq
for q in oqim:
q = q.strip()
if q and not q.startswith("#"):
yield q
def sonlar(oqim): # oraliq
for q in oqim:
yield int(q)
jami = sum(sonlar(tozala(qatorlar("data.txt")))) # yakunlovchi Yakunlovchi bo'lmasa, hech narsa bajarilmaydi. sonlar(tozala(...)) shunchaki generatorlar zanjirini quradi — fayl hatto ochilmaydi.
2.2. Elementlar qanday oqadi
Ro'yxatlar bilan ishlash bosqichma-bosqich bo'ladi: avval hamma qatorlar o'qiladi, keyin hammasi tozalanadi, keyin hammasi songa aylanadi.
Generator quvurida esa elementma-element: birinchi qator barcha bosqichlardan o'tadi, keyin ikkinchisi va hokazo.
Ro'yxatlar: Generatorlar:
o'qi 1, o'qi 2, o'qi 3 o'qi 1 → tozala 1 → son 1
tozala 1, tozala 2, tozala 3 o'qi 2 → tozala 2 → son 2
son 1, son 2, son 3 o'qi 3 → tozala 3 → son 3Buning oqibatlari:
- Xotira — bir vaqtda bitta element
- Erta to'xtash — yakunlovchi to'xtasa, manba ham to'xtaydi
- Birinchi natija tez — hammasini kutmasdan
- Xato kechikadi — 1 000 000-qatordagi xato faqat shunga yetganda chiqadi
2.3. Bosqich turlari: funksiya yoki ifoda
Oddiy bosqich uchun generator ifodasi yetarli:
tozalangan = (q.strip() for q in oqim if q.strip())Generator funksiya kerak bo'ladi, agar bosqichda:
- holat bo'lsa (hisoblagich, oldingi element, bufer)
- bir elementdan bir nechta yoki nol element chiqsa
try/exceptkerak bo'lsa- nomi va hujjati kerak bo'lsa (qayta ishlatiladigan bosqich)
2.4. itertools — tayyor bosqichlar
| Funksiya | Nima qiladi |
|---|---|
islice(it, n) / islice(it, a, b) |
Kesish — it[a:b] ning dangasa varianti |
takewhile(shart, it) |
Shart bajarilguncha oladi |
dropwhile(shart, it) |
Shart bajarilguncha tashlaydi, keyin hammasini beradi |
chain(a, b, ...) |
Oqimlarni ketma-ket ulaydi |
chain.from_iterable(oqimlar) |
Oqimlar oqimini tekislaydi |
groupby(it, key) |
Ketma-ket teng elementlarni guruhlaydi |
accumulate(it, f) |
Yig'ma natijalar (jami, maksimum) |
pairwise(it) (3.10+) |
(a, b), (b, c), ... |
batched(it, n) (3.12+) |
n talik kortejlar |
tee(it, n) |
Bitta iteratordan n ta mustaqil nusxa |
count(), cycle(), repeat() |
Cheksiz manbalar |
compress(it, belgilar) |
Belgi rost bo'lganlarini oladi |
starmap(f, it) |
f(*el) |
To'liq itertools 15-qismda. Bu yerda — generatorlar bilan eng ko'p ishlatiladiganlari.
2.5. groupby tuzog'i
groupby SQL'dagi GROUP BY emas. U faqat yonma-yon turgan teng elementlarni birlashtiradi:
from itertools import groupby
[(k, len(list(g))) for k, g in groupby("aabba")]
# [('a', 2), ('b', 2), ('a', 1)] ⚠️ 'a' ikki guruhdaTo'liq guruhlash uchun avval shu kalit bo'yicha saralang. Oqim juda katta bo'lsa — saralash o'rniga lug'at ishlating.
Ikkinchi tuzoq: guruh iteratori keyingi guruhga o'tishi bilan yaroqsiz bo'ladi:
guruhlar = list(groupby("aabb"))
[list(g) for k, g in guruhlar] # [[], []] ⚠️ hammasi bo'sh (Python 3.14) Guruhni darhol iste'mol qiling: {k: list(g) for k, g in groupby(...)}.
2.6. tee tuzog'i
tee bitta iteratordan bir nechta nusxa yasaydi. Lekin nusxalardan biri oldinga ketsa, orqada qolgani uchun o'tkazib yuborilgan elementlar xotirada saqlanadi:
a, b = tee(katta_oqim)
max(a) # a oxirigacha bordi
min(b) # ⚠️ butun oqim xotirada saqlangan ediBundan tashqari, tee dan keyin asl iteratorni ishlatmang — nusxalar buziladi.
Ikki natija kerak bo'lsa, ko'pincha bitta o'tishda hisoblash yaxshiroq (Misol 2).
2.7. Quvurdagi xatolar
Dangasa quvurda xato iste'mol paytida, ko'pincha yakunlovchi ichida chiqadi. Uch strategiya bor:
| Strategiya | Qachon |
|---|---|
| To'xtash — xatoni o'tkazib yuborish | Ma'lumot sifati kafolatlangan, xato — bug |
| O'tkazib yuborish — bosqich ichida ushlab, davom etish | Bir nechta buzuq yozuv kutiladi |
| Ajratish — xatolarni alohida oqimga yig'ish | Buzuqlar hisobotda kerak |
def xavfsiz_son(oqim, xatolar):
for tartib, q in enumerate(oqim, 1):
try:
yield int(q)
except ValueError as e:
xatolar.append((tartib, q, e)) # ⭐ davom etamiz2.8. Qachon generator kerak emas
- Ma'lumot kichik va bir necha marta ishlatiladi — ro'yxat soddaroq
len(), indeks yoki teskari tartib kerak- Natijani saralash kerak —
sorted()baribir hammasini yig'adi - Bosqichlar orasida tasodifiy kirish kerak
- Debug paytida oraliq natijalarni ko'rish muhim
Qoida: ma'lumot xotiraga sig'masa yoki erta to'xtash kerak bo'lsa — generator; aks holda — o'qilishi osonrog'i.
3. Tez ma'lumotnoma
Quvur
manba = (...) # fayl, range, API
bosqich1 = (f(x) for x in manba)
bosqich2 = (x for x in bosqich1 if shart(x))
natija = sum(bosqich2) # ⭐ faqat shu yerda ishlaydiRetseptlar
next(it, None) birinchi element
deque(it, maxlen=1) oxirgi element (xotirasiz)
deque(it, maxlen=0) oxirigacha iste'mol qilish
islice(it, n) birinchi n ta
batched(it, n) n talik bo'laklar (3.12+)
pairwise(it) qo'shni juftlar (3.10+)
chain.from_iterable(ichma_ich) bir qavat tekislash
heapq.merge(a, b) saralangan oqimlarni birlashtirish
heapq.nlargest(n, it, key) eng katta n ta (xotira O(n))Tuzoqlar
groupby faqat yonma-yon; guruhni darhol iste'mol qiling
tee orqada qolgan nusxa uchun hammasi xotirada
yakunlovchi yo'q hech narsa bajarilmaydi
sorted(generator) dangasalik yo'qoladi — hammasi yig'iladi4. Batafsil misollar
Misol 1 — Quvurda elementlar qanday oqadi
"""Ro'yxat va generator quvurlarini bajarilish tartibi bo'yicha solishtirish."""
tartib = []
def manba(qatorlar):
for q in qatorlar:
tartib.append(f"o'qi:{q.strip()!r}")
yield q
def tozala(oqim):
for q in oqim:
q = q.strip()
tartib.append(f"tozala:{q!r}")
if q and not q.startswith("#"):
yield q
def son(oqim):
for q in oqim:
tartib.append(f"son:{q}")
yield int(q)
FAYL = ["10\n", "# izoh\n", "20\n", "\n", "30\n"]
print("=== 1. Ro'yxatlar bilan: bosqichma-bosqich ===")
tartib.clear()
a = list(manba(FAYL))
b = list(tozala(a))
c = list(son(b))
print(f" natija: {sum(c)}")
for qadam in tartib:
print(f" {qadam}")
print("\n=== 2. Generatorlar bilan: elementma-element ===")
tartib.clear()
quvur = son(tozala(manba(FAYL)))
print(f" quvur qurildi, bajarilgan qadamlar: {len(tartib)}")
print(f" natija: {sum(quvur)}")
for qadam in tartib:
print(f" {qadam}")
print("\n=== 3. Erta to'xtash manbani ham to'xtatadi ===")
tartib.clear()
quvur = son(tozala(manba(FAYL)))
birinchi_katta = next(x for x in quvur if x > 15)
print(f" 15 dan katta birinchisi: {birinchi_katta}")
print(f" bajarilgan qadamlar: {tartib}")
print(f" ⭐ '30' hech qachon o'qilmadi")
print("\n=== 4. Yakunlovchisiz — hech narsa ===")
tartib.clear()
quvur = son(tozala(manba(["1\n", "x\n"])))
print(f" xato bo'lishi kerak bo'lgan quvur qurildi, qadamlar: {len(tartib)}")
try:
list(quvur)
except ValueError as e:
print(f" faqat iste'molda: ❌ ValueError: {e}")
print(f" xatogacha qadamlar: {tartib}")Natijaning muhim qismi:
=== 1. Ro'yxatlar bilan: bosqichma-bosqich ===
natija: 60
o'qi:'10'
o'qi:'# izoh'
o'qi:'20'
o'qi:''
o'qi:'30'
tozala:'10'
tozala:'# izoh'
tozala:'20'
tozala:''
tozala:'30'
son:10
son:20
son:30
=== 2. Generatorlar bilan: elementma-element ===
quvur qurildi, bajarilgan qadamlar: 0
natija: 60
o'qi:'10'
tozala:'10'
son:10
o'qi:'# izoh'
tozala:'# izoh'
o'qi:'20'
tozala:'20'
son:20
o'qi:''
tozala:''
o'qi:'30'
tozala:'30'
son:30
=== 3. Erta to'xtash manbani ham to'xtatadi ===
15 dan katta birinchisi: 20
bajarilgan qadamlar: ["o'qi:'10'", "tozala:'10'", 'son:10', "o'qi:'# izoh'", "tozala:'# izoh'", "o'qi:'20'", "tozala:'20'", 'son:20']
⭐ '30' hech qachon o'qilmadi
=== 4. Yakunlovchisiz — hech narsa ===
xato bo'lishi kerak bo'lgan quvur qurildi, qadamlar: 0
faqat iste'molda: ❌ ValueError: invalid literal for int() with base 10: 'x'
xatogacha qadamlar: ["o'qi:'1'", "tozala:'1'", 'son:1', "o'qi:'x'", "tozala:'x'", 'son:x']Nima ko'rsatdi: 2.1, 2.2-bo'limlar.
Misol 2 — itertools bilan generatorlar va ularning tuzoqlari
"""islice, takewhile, dropwhile, groupby, tee, batched, pairwise — amalda."""
import itertools
import tracemalloc
from collections import defaultdict
print("=== 1. Cheksiz manbani cheklash ===")
def tub_sonlar():
topilgan = []
for n in itertools.count(2):
if all(n % t for t in topilgan if t * t <= n):
topilgan.append(n)
yield n
print(f" birinchi 10 tub: {list(itertools.islice(tub_sonlar(), 10))}")
print(f" 100 dan kichiklar: {list(itertools.takewhile(lambda x: x < 100, tub_sonlar()))[-5:]} (oxirgi 5)")
print(f" 1000 dan keyingi 3 ta: {list(itertools.islice(itertools.dropwhile(lambda x: x < 1000, tub_sonlar()), 3))}")
print("\n=== 2. ⚠️ groupby faqat yonma-yonlarni birlashtiradi ===")
SOTUVLAR = [("olma", 3), ("anor", 1), ("olma", 2), ("olma", 5), ("anor", 4)]
yomon = [(k, sum(s for _, s in g)) for k, g in itertools.groupby(SOTUVLAR, key=lambda x: x[0])]
print(f" saralanmagan: {yomon}")
saralangan = sorted(SOTUVLAR, key=lambda x: x[0])
togri = [(k, sum(s for _, s in g)) for k, g in itertools.groupby(saralangan, key=lambda x: x[0])]
print(f" saralangan: {togri}")
lugat = defaultdict(int)
for mahsulot, soni in SOTUVLAR:
lugat[mahsulot] += soni
print(f" lug'at bilan (saralashsiz): {dict(lugat)}")
print("\n=== 3. ⚠️ groupby guruhlarini keyin iste'mol qilish ===")
guruhlar = list(itertools.groupby("aaabbc"))
print(f" list(groupby) dan keyin: {[(k, list(g)) for k, g in guruhlar]}")
print(f" darhol iste'mol: {[(k, list(g)) for k, g in itertools.groupby('aaabbc')]}")
print("\n=== 4. ⚠️ tee xotirasi ===")
def katta_oqim(n=300_000):
for i in range(n):
yield i * 3 % 1_000_003
tracemalloc.start()
a, b = itertools.tee(katta_oqim())
eng_katta = max(a)
_, tepa_tee = tracemalloc.get_traced_memory()
eng_kichik = min(b)
tracemalloc.stop()
tracemalloc.start()
eng_katta2, eng_kichik2 = float("-inf"), float("inf")
for x in katta_oqim():
eng_katta2 = max(eng_katta2, x)
eng_kichik2 = min(eng_kichik2, x)
_, tepa_bitta = tracemalloc.get_traced_memory()
tracemalloc.stop()
print(f" tee (max, keyin min): {eng_katta}, {eng_kichik} xotira cho'qqisi: {tepa_tee / 1024:,.0f} KB")
print(f" bitta o'tishda: {eng_katta2}, {eng_kichik2} xotira cho'qqisi: {tepa_bitta / 1024:,.0f} KB")
print("\n=== 5. batched, pairwise, accumulate ===")
harorat = [18, 21, 19, 24, 26, 25, 22]
print(f" batched(3): {list(itertools.batched(harorat, 3))}")
print(f" o'zgarishlar (pairwise): {[b - a for a, b in itertools.pairwise(harorat)]}")
print(f" yig'ma maksimum: {list(itertools.accumulate(harorat, max))}")
print(f" yig'ma jami: {list(itertools.accumulate(harorat))}")
print("\n=== 6. chain.from_iterable — fayllar oqimini tekislash ===")
FAYLLAR = {"yanvar.csv": ["a,1", "b,2"], "fevral.csv": ["c,3"], "mart.csv": []}
def fayl_qatorlari(nom):
print(f" ochildi: {nom}")
yield from FAYLLAR[nom]
barchasi = itertools.chain.from_iterable(fayl_qatorlari(n) for n in FAYLLAR)
print(f" birinchi qator: {next(barchasi)} ⭐ faqat birinchi fayl ochildi")
print(f" qolganlari: {list(barchasi)}")Natijaning muhim qismi:
=== 1. Cheksiz manbani cheklash ===
birinchi 10 tub: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
100 dan kichiklar: [73, 79, 83, 89, 97] (oxirgi 5)
1000 dan keyingi 3 ta: [1009, 1013, 1019]
=== 2. ⚠️ groupby faqat yonma-yonlarni birlashtiradi ===
saralanmagan: [('olma', 3), ('anor', 1), ('olma', 7), ('anor', 4)]
saralangan: [('anor', 5), ('olma', 10)]
lug'at bilan (saralashsiz): {'olma': 10, 'anor': 5}
=== 3. ⚠️ groupby guruhlarini keyin iste'mol qilish ===
list(groupby) dan keyin: [('a', []), ('b', []), ('c', [])]
darhol iste'mol: [('a', ['a', 'a', 'a']), ('b', ['b', 'b']), ('c', ['c'])]
=== 4. ⚠️ tee xotirasi ===
tee (max, keyin min): 899997, 0 xotira cho'qqisi: 12,002 KB
bitta o'tishda: 899997, 0 xotira cho'qqisi: 0 KB
=== 5. batched, pairwise, accumulate ===
batched(3): [(18, 21, 19), (24, 26, 25), (22,)]
o'zgarishlar (pairwise): [3, -2, 5, 2, -1, -3]
yig'ma maksimum: [18, 21, 21, 24, 26, 26, 26]
yig'ma jami: [18, 39, 58, 82, 108, 133, 155]
=== 6. chain.from_iterable — fayllar oqimini tekislash ===
ochildi: yanvar.csv
birinchi qator: a,1 ⭐ faqat birinchi fayl ochildi
ochildi: fevral.csv
ochildi: mart.csv
qolganlari: ['b,2', 'c,3']Nima ko'rsatdi: 2.4, 2.5, 2.6-bo'limlar.
Misol 3 — Retseptlar kutubxonasi
"""Kundalik ishda kerak bo'ladigan generator retseptlari va ularning sinovlari."""
import heapq
import itertools
from collections import deque
def bolaklar(oqim, hajm):
"""[1..7], 3 → [1,2,3], [4,5,6], [7] — batched ning ro'yxat varianti."""
it = iter(oqim)
while bolak := list(itertools.islice(it, hajm)):
yield bolak
def siljuvchi_oyna(oqim, hajm):
"""[1,2,3,4], 3 → (1,2,3), (2,3,4)."""
it = iter(oqim)
oyna = deque(itertools.islice(it, hajm), maxlen=hajm)
if len(oyna) == hajm:
yield tuple(oyna)
for el in it:
oyna.append(el)
yield tuple(oyna)
def takrorsiz(oqim, kalit=None):
"""Birinchi uchragan tartibni saqlab takrorlarni tashlaydi."""
korilgan = set()
for el in oqim:
k = el if kalit is None else kalit(el)
if k not in korilgan:
korilgan.add(k)
yield el
def navbatma_navbat(*oqimlar):
"""'ABC', 'D', 'EF' → A D E B F C."""
faol = deque(iter(o) for o in oqimlar)
while faol:
it = faol.popleft()
try:
yield next(it)
except StopIteration:
continue
faol.append(it)
def oxirgi(oqim, sukut=None):
"""Oxirgi elementni xotiraga yig'masdan."""
d = deque(oqim, maxlen=1)
return d[0] if d else sukut
def yetkaz(oqim, qadam):
"""Har `qadam` elementda bir marta progress chiqaradi, elementlarni o'zgartirmaydi."""
for tartib, el in enumerate(oqim, 1):
if tartib % qadam == 0:
print(f" ... {tartib:,} ta ishlandi")
yield el
SINOVLAR = [
("bolaklar", list(bolaklar(range(1, 8), 3)), [[1, 2, 3], [4, 5, 6], [7]]),
("bolaklar (bo'sh)", list(bolaklar([], 3)), []),
("siljuvchi_oyna", list(siljuvchi_oyna([1, 2, 3, 4], 3)), [(1, 2, 3), (2, 3, 4)]),
("siljuvchi_oyna (qisqa)", list(siljuvchi_oyna([1, 2], 3)), []),
("takrorsiz", list(takrorsiz("abracadabra")), ["a", "b", "r", "c", "d"]),
("takrorsiz (kalit)", list(takrorsiz(["Olma", "olma", "ANOR"], str.lower)), ["Olma", "ANOR"]),
("navbatma_navbat", "".join(navbatma_navbat("ABC", "D", "EF")), "ADEBFC"),
("oxirgi", oxirgi(x * x for x in range(1_000_000)), 999_998_000_001),
("oxirgi (bo'sh)", oxirgi(iter([]), "yo'q"), "yo'q"),
]
print("=== 1. Retseptlar sinovi ===")
for nom, haqiqiy, kutilgan in SINOVLAR:
belgi = "✅" if haqiqiy == kutilgan else "❌"
print(f" {belgi} {nom:<24} → {haqiqiy}")
print("\n=== 2. Saralangan oqimlarni birlashtirish (heapq.merge) ===")
toshkent = [("08:01", "T", 120), ("08:05", "T", 90), ("08:20", "T", 300)]
samarqand = [("08:02", "S", 50), ("08:15", "S", 75)]
buxoro = [("08:00", "B", 10), ("08:30", "B", 40)]
for vaqt, filial, summa in heapq.merge(toshkent, samarqand, buxoro):
print(f" {vaqt} {filial} {summa:>4}")
print("\n=== 3. Siljuvchi o'rtacha — oqimda ===")
narxlar = [100, 102, 101, 105, 110, 108, 115]
for oyna in siljuvchi_oyna(narxlar, 3):
print(f" {oyna} → o'rtacha {sum(oyna) / 3:.1f}")
print("\n=== 4. Progress chiqaruvchi bosqich ===")
jami = sum(yetkaz((x for x in range(250_000)), 100_000))
print(f" jami: {jami:,}")
print("\n=== 5. Eng katta N ta — heapq.nlargest xotirasi ===")
import tracemalloc
tracemalloc.start()
top = heapq.nlargest(3, (x * 7919 % 1_000_003 for x in range(500_000)))
_, tepa = tracemalloc.get_traced_memory()
tracemalloc.stop()
tracemalloc.start()
top2 = sorted([x * 7919 % 1_000_003 for x in range(500_000)], reverse=True)[:3]
_, tepa2 = tracemalloc.get_traced_memory()
tracemalloc.stop()
print(f" nlargest(generator): {top} xotira: {tepa / 1024:,.0f} KB")
print(f" sorted(ro'yxat)[:3]: {top2} xotira: {tepa2 / 1024:,.0f} KB")Natijaning muhim qismi:
=== 1. Retseptlar sinovi ===
✅ bolaklar → [[1, 2, 3], [4, 5, 6], [7]]
✅ bolaklar (bo'sh) → []
✅ siljuvchi_oyna → [(1, 2, 3), (2, 3, 4)]
✅ siljuvchi_oyna (qisqa) → []
✅ takrorsiz → ['a', 'b', 'r', 'c', 'd']
✅ takrorsiz (kalit) → ['Olma', 'ANOR']
✅ navbatma_navbat → ADEBFC
✅ oxirgi → 999998000001
✅ oxirgi (bo'sh) → yo'q
=== 2. Saralangan oqimlarni birlashtirish (heapq.merge) ===
08:00 B 10
08:01 T 120
08:02 S 50
08:05 T 90
08:15 S 75
08:20 T 300
08:30 B 40
=== 3. Siljuvchi o'rtacha — oqimda ===
(100, 102, 101) → o'rtacha 101.0
(102, 101, 105) → o'rtacha 102.7
(101, 105, 110) → o'rtacha 105.3
(105, 110, 108) → o'rtacha 107.7
(110, 108, 115) → o'rtacha 111.0
=== 4. Progress chiqaruvchi bosqich ===
... 100,000 ta ishlandi
... 200,000 ta ishlandi
jami: 31,249,875,000
=== 5. Eng katta N ta — heapq.nlargest xotirasi ===
nlargest(generator): [1000002, 1000000, 999999] xotira: 1 KB
sorted(ro'yxat)[:3]: [1000002, 1000000, 999999] xotira: 25,549 KBNima ko'rsatdi: 2.3, 2.4-bo'limlar va 3-bo'limdagi retseptlar.
Misol 4 — Amaliy: bir nechta filialdan oqimli sotuv hisoboti
"""Uch filialning CSV oqimlari → tahlil → tekshirish → kunlik hisobot. Xatolar alohida yig'iladi."""
import heapq
import io
import itertools
import tracemalloc
from collections import defaultdict
from dataclasses import dataclass
from datetime import date
FILIAL_URUG = {"TSH": 0, "SAM": 123_457, "BUX": 345_679}
def filial_fayli(filial, kunlar, har_kun):
"""Sun'iy CSV: har filialda ba'zi qatorlar ataylab buzuq."""
qatorlar = ["sana,chek,summa\n"]
urug = FILIAL_URUG[filial]
for kun in range(1, kunlar + 1):
for i in range(har_kun):
chek = f"{filial}-{kun:02d}-{i:05d}"
if i % 997 == 13:
qatorlar.append(f"2026-09-{kun:02d},{chek},noma'lum\n") # buzuq summa
elif i % 1499 == 7:
qatorlar.append(f"2026-09-{kun:02d},{chek}\n") # ustun yetishmaydi
else:
summa = (i * 7919 + kun * 104729 + urug) % (380_000 + urug // 3) + 10_000
qatorlar.append(f"2026-09-{kun:02d},{chek},{summa}\n")
return io.StringIO("".join(qatorlar))
@dataclass(frozen=True, slots=True)
class Sotuv:
sana: date
filial: str
chek: str
summa: int
# ── Bosqichlar ──
def csv_qatorlari(filial, fayl):
sarlavha = next(fayl, None)
if sarlavha is None:
return
for raqam, qator in enumerate(fayl, 2):
yield filial, raqam, qator.rstrip("\n")
def tahlil(oqim, xatolar):
for filial, raqam, qator in oqim:
qismlar = qator.split(",")
try:
if len(qismlar) != 3:
raise ValueError(f"{len(qismlar)} ustun, 3 kutilgan")
yil, oy, kun = map(int, qismlar[0].split("-"))
yield Sotuv(date(yil, oy, kun), filial, qismlar[1], int(qismlar[2]))
except ValueError as e:
xatolar[filial].append((raqam, str(e)))
def sana_boyicha(oqimlar):
"""Har filial fayli sana bo'yicha saralangan — ularni birlashtiramiz."""
return heapq.merge(*oqimlar, key=lambda s: s.sana)
def kunlik_hisobot(sotuvlar):
for kun, guruh in itertools.groupby(sotuvlar, key=lambda s: s.sana):
jami, soni, filiallar = 0, 0, defaultdict(int)
eng_katta = None
for s in guruh:
jami += s.summa
soni += 1
filiallar[s.filial] += s.summa
if eng_katta is None or s.summa > eng_katta.summa:
eng_katta = s
yield kun, soni, jami, dict(filiallar), eng_katta
FILIALLAR = ["TSH", "SAM", "BUX"]
KUNLAR, HAR_KUN = 5, 20_000
xatolar = defaultdict(list)
fayllar = {f: filial_fayli(f, KUNLAR, HAR_KUN) for f in FILIALLAR}
tracemalloc.start()
quvurlar = [tahlil(csv_qatorlari(f, fayl), xatolar) for f, fayl in fayllar.items()]
hisobot = list(kunlik_hisobot(sana_boyicha(quvurlar)))
_, tepa = tracemalloc.get_traced_memory()
tracemalloc.stop()
print("=== 1. Kunlik hisobot ===")
print(f" {'Sana':<11} {'Cheklar':>8} {'Jami (mln)':>11} {'TSH':>7} {'SAM':>7} {'BUX':>7} Eng katta chek")
print(" " + "─" * 84)
for kun, soni, jami, filiallar, eng_katta in hisobot:
f = {k: v / 1e6 for k, v in filiallar.items()}
print(f" {kun} {soni:>8,} {jami / 1e6:>11,.1f} {f['TSH']:>7,.1f} {f['SAM']:>7,.1f} "
f"{f['BUX']:>7,.1f} {eng_katta.chek} ({eng_katta.summa:,})")
print("\n=== 2. Xatolar filial bo'yicha ===")
for filial in FILIALLAR:
royxat = xatolar[filial]
print(f" {filial}: {len(royxat)} ta buzuq qator, birinchisi: {royxat[0]}")
jami_qator = KUNLAR * HAR_KUN * len(FILIALLAR)
jami_xato = sum(len(v) for v in xatolar.values())
print(f"\n=== 3. Xulosa ===")
print(f" jami qator: {jami_qator:,}, to'g'ri: {sum(s for _, s, *_ in hisobot):,}, buzuq: {jami_xato:,}")
print(f" quvur xotira cho'qqisi: {tepa / 1_048_576:.2f} MB")
print("\n=== 4. Butun davrdagi eng katta 3 chek ===")
for f in fayllar.values():
f.seek(0)
eng_kattalar = heapq.nlargest(
3,
itertools.chain.from_iterable(
tahlil(csv_qatorlari(fl, fayl), defaultdict(list)) for fl, fayl in fayllar.items()
),
key=lambda s: s.summa,
)
for s in eng_kattalar:
print(f" {s.chek} {s.summa:,} so'm")Natijaning muhim qismi:
=== 1. Kunlik hisobot ===
Sana Cheklar Jami (mln) TSH SAM BUX Eng katta chek
────────────────────────────────────────────────────────────────────────────────────
2026-09-01 59,895 13,539.2 3,995.2 4,404.0 5,140.0 BUX-01-08323 (505,187)
2026-09-02 59,895 13,541.8 3,993.0 4,404.8 5,144.0 BUX-02-06121 (505,188)
2026-09-03 59,895 13,541.6 3,991.3 4,404.2 5,146.1 BUX-03-03919 (505,189)
2026-09-04 59,895 13,538.8 3,991.8 4,403.3 5,143.6 BUX-04-01717 (505,190)
2026-09-05 59,895 13,537.6 3,994.6 4,403.2 5,139.8 BUX-05-08958 (505,182)
=== 2. Xatolar filial bo'yicha ===
TSH: 175 ta buzuq qator, birinchisi: (9, '2 ustun, 3 kutilgan')
SAM: 175 ta buzuq qator, birinchisi: (9, '2 ustun, 3 kutilgan')
BUX: 175 ta buzuq qator, birinchisi: (9, '2 ustun, 3 kutilgan')
=== 3. Xulosa ===
jami qator: 300,000, to'g'ri: 299,475, buzuq: 525
quvur xotira cho'qqisi: 0.09 MB
=== 4. Butun davrdagi eng katta 3 chek ===
BUX-04-01717 505,190 so'm
BUX-03-03919 505,189 so'm
BUX-02-06121 505,188 so'mNima ko'rsatdi: 2.1, 2.2, 2.4, 2.5, 2.7-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Quvur qurilganda ishlay boshlaydi" | Faqat yakunlovchi iste'mol qilganda |
| "Generator quvuri bosqichma-bosqich ishlaydi" | Elementma-element: har element butun quvurdan o'tadi |
"groupby SQL GROUP BY kabi" |
Faqat yonma-yon elementlarni guruhlaydi |
"tee xotira tejaydi" |
Orqada qolgan nusxa uchun elementlar saqlanadi |
"sorted(generator) dangasa" |
Hammasini ro'yxatga yig'adi |
| "Generator doim ro'yxatdan tez" | Kichik ma'lumotda ko'pincha sekinroq; foydasi — xotira va erta to'xtash |
| "Xato quvur qurilgan joyda chiqadi" | Iste'mol qilingan joyda |
| "Eng katta N tani topish uchun saralash kerak" | heapq.nlargest — O(N) xotira |
6. Keng tarqalgan xatolar va yechimlari
1. Quvurni qurib, iste'mol qilmaslik
def saqla(oqim):
for y in oqim:
yield baza.yoz(y) # ❌ generator — hech narsa yozilmaydi
saqla(yozuvlar) # ❌ natija tashlab yuborildi
def saqla(oqim): # ✅ yakunlovchi — oddiy funksiya
for y in oqim:
baza.yoz(y)2. groupby dan oldin saralamaslik
groupby(sotuvlar, key=lambda s: s.mahsulot) # ❌
groupby(sorted(sotuvlar, key=lambda s: s.mahsulot), key=...) # ✅3. groupby guruhlarini keyin ishlatish
guruhlar = list(groupby(r, key))
for k, g in guruhlar: list(g) # ❌ guruhlar bo'sh
{k: list(g) for k, g in groupby(r, key)} # ✅4. tee bilan ikki marta o'tish
a, b = tee(oqim)
ortacha = sum(a) / sum(1 for _ in b) # ⚠️ butun oqim xotirada
jami = soni = 0 # ✅ bitta o'tish
for x in oqim:
jami += x; soni += 15. Quvur o'rtasida ro'yxatga aylantirish
qatorlar = [q for q in fayl] # ⚠️ dangasalik yo'qoldi
xatolar = (q for q in qatorlar if "ERROR" in q)
xatolar = (q for q in fayl if "ERROR" in q) # ✅6. Faylni generator ichida with siz ochish
def qatorlar(yol):
f = open(yol) # ⚠️ quvur erta to'xtasa, qachon yopiladi?
yield from f
def qatorlar(yol):
with open(yol) as f: # ✅ generator yopilganda fayl ham yopiladi
yield from f7. Butun oqimni saralash uchun eng kattani topish
sorted(oqim, key=k, reverse=True)[:10] # ⚠️ O(n) xotira, O(n log n)
heapq.nlargest(10, oqim, key=k) # ✅ O(10) xotira8. Buzuq qatorda butun quvurni to'xtatish
yozuvlar = (tahlil(q) for q in fayl) # ❌ bitta buzuq qator — hammasi to'xtaydi
def xavfsiz(oqim, xatolar): # ✅ bosqich ichida ushlash
for q in oqim:
try: yield tahlil(q)
except ValueError as e: xatolar.append((q, e))7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 10.1–10.3-darslar (o'tilgan): iterator protokoli va
yieldmexanizmi - 6.17-dars (o'tilgan): generator ifodalari
- 9.8-dars (o'tilgan): xatolar strategiyasi — quvurdagi o'tkazib yuborish va ajratish
- 10.5-dars:
yield from— bosqichlarni bir-biriga ulash - 15-qism:
itertools,heapq,collectionsto'liq - 16-qism: CSV, JSON Lines va katta fayllar bilan oqimli ishlash
- 24-qism: pandas'dagi
chunksize— xuddi shu g'oya jadvallar uchun
8. Eng yaxshi amaliyotlar
Har bosqich bitta ish qilsin. O'qish, tozalash, tahlil, filtr — alohida generatorlar. Ular qayta ishlatiladi va alohida sinaladi.
Yakunlovchi — oddiy funksiya. Yon ta'sirli ishni (
yoz,yubor) generator qilmang, aks holda uni hech kim iste'mol qilmay qolishi mumkin.Resursni manba generatorida
withbilan oching. Quvur erta to'xtasa ham yopiladi.groupbydan oldin saralang yoki lug'at ishlating.teeo'rniga bitta o'tishda hisoblang. Bir nechta natija kerak bo'lsa, hisoblagichlarni bitta siklda yuriting.Eng katta/kichik N ta —
heapq. Butun oqimni saralamang.Buzuq yozuvlarni bosqich ichida ushlang va alohida yig'ing. Hisobotda nechta va qaysilar ekani ko'rinsin.
Kichik ma'lumotda o'qilishini tanlang. Generator — xotira va erta to'xtash uchun, "chiroyli" ko'rinish uchun emas.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
from itertools import groupby, islice, takewhile, dropwhile, tee, pairwise, accumulate, chain, count
from collections import deque
1. print([(k, len(list(g))) for k, g in groupby("aabccca")])
2. print(list(takewhile(lambda x: x < 3, [1, 2, 5, 1])), list(dropwhile(lambda x: x < 3, [1, 2, 5, 1])))
3. print(list(islice(count(10, 5), 3)))
4. g = (x * x for x in range(5))
print(list(islice(g, 2)), list(g))
5. print(deque((x for x in range(10)), maxlen=1)[0])
6. a, b = tee([1, 2, 3])
print(list(a), list(b))
7. print([b - a for a, b in pairwise([3, 8, 6])])
8. print(list(accumulate([2, 5, 1, 7], max)))
9. print(list(chain.from_iterable(["ab", [1, 2]])))
10. guruhlar = list(groupby("aab"))
print([list(g) for _, g in guruhlar])
11. def bosqich(oqim):
for x in oqim:
print("b", x, end=" ")
yield x * 10
q = bosqich(iter([1, 2, 3]))
print(next(q))
12. import heapq
print(list(heapq.merge([1, 4, 9], [2, 3, 10])))Javoblar
[('a', 2), ('b', 1), ('c', 3), ('a', 1)]— oxirgiaalohida guruh[1, 2] [5, 1]—takewhilebirinchi buzilishda to'xtaydi,dropwhileundan keyin hammasini beradi[10, 15, 20][0, 1] [4, 9, 16]—islicegeneratordan ikkitasini oldi9— faqat oxirgisi saqlandi[1, 2, 3] [1, 2, 3][5, -2][2, 5, 5, 7]['a', 'b', 1, 2][[], []]—list()butun oqimni o'tib chiqdi, guruh iteratorlari yaroqsiz bo'ldi (eski versiyalarda oxirgi guruh ba'zan qolgan elementni berardi — bunga tayanmang)b 1 10— faqat bitta element quvurdan o'tdi[1, 2, 3, 4, 9, 10]
Vazifa 2: Xatolarni tuzating
1. def eksport(yozuvlar, fayl):
for y in yozuvlar:
yield fayl.write(f"{y}\n")
eksport(barcha_yozuvlar, chiqish)
2. from itertools import groupby
for mahsulot, guruh in groupby(sotuvlar, key=lambda s: s["mahsulot"]):
print(mahsulot, sum(s["summa"] for s in guruh))
3. from itertools import tee
a, b = tee(katta_log_oqimi)
xatolar = sum(1 for q in a if "ERROR" in q)
ogohlar = sum(1 for q in b if "WARN" in q)
4. top10 = sorted(juda_katta_oqim, key=lambda y: y.ball, reverse=True)[:10]
5. def qatorlar(yol):
f = open(yol)
for q in f:
yield qJavoblar
1. def eksport(yozuvlar, fayl): # generator emas — yakunlovchi
for y in yozuvlar:
fayl.write(f"{y}\n")
2. sotuvlar = sorted(sotuvlar, key=lambda s: s["mahsulot"]) # avval saralash
# yoki: defaultdict(int) bilan saralashsiz yig'ish
3. xatolar = ogohlar = 0 # bitta o'tish, tee siz
for q in katta_log_oqimi:
xatolar += "ERROR" in q
ogohlar += "WARN" in q
4. import heapq
top10 = heapq.nlargest(10, juda_katta_oqim, key=lambda y: y.ball)
5. def qatorlar(yol):
with open(yol) as f:
yield from fVazifa 3: Log tahlilchi quvuri
Veb-server logi (sana vaqt metod yo'l kod ms) uchun quvur yozing:
qatorlar(yol)— manba,withbilantahlil(oqim, xatolar)— buzuq qatorlarnixatolarga yig'sinvaqt_oraligi(oqim, bosh, oxir)—dropwhile+takewhilebilan (log sana bo'yicha saralangan)eng_sekin(oqim, n)—heapq.nlargest- 5 000 000 qatorli sun'iy log bilan xotira 20 MB dan oshmasligini
tracemallocbilan tekshiring
Vazifa 4: Retseptlarni kengaytiring
Misol 3 ga qo'shing va har biriga sinov yozing:
birinchi_n_takrorsiz(oqim, n)—nta noyob element topilgach to'xtasinbolaklab_vaqt(oqim, kalit, soniya)— vaqt oynasi bo'yicha guruhlash (masalan, har 60 soniya)aralash_nlargest(oqimlar, n, key)— bir nechta oqimdan eng kattantatekislash(ichma_ich, chuqurlik)— berilgan chuqurlikkacha tekislash (satrlarni harflarga bo'lmasin)
Vazifa 5: tee siz statistika
Generatorni bir marta aylanib, quyidagilarni hisoblaydigan statistika(oqim) yozing: soni, jami, o'rtacha, min, max, dispersiya va medianga yaqin qiymat (maslahat: P² algoritmi yoki heapq bilan ikki uyum). tee bilan yozilgan variant bilan xotirani solishtiring.
Vazifa 6: Oqimli birlashtirish (join)
Ikki katta CSV oqimi bor: buyurtmalar (mijoz_id bo'yicha saralangan) va mijozlar (id bo'yicha saralangan). Ularni ikkalasini ham xotiraga yuklamasdan birlashtiradigan birlashtir(buyurtmalar, mijozlar) generatorini yozing (merge join). Mijozi topilmagan buyurtmalarni alohida ro'yxatga yig'ing.
Vazifa 7: O'ylash
Generator quvuri Unix'dagi cat log | grep 500 | sort | head -10 ga o'xshatiladi. Ular qaysi jihatlarda haqiqatan o'xshash va qaysi jihatlarda tubdan farq qiladi? Nega bu quvurdagi sort ikkala dunyoda ham muammoli?
Javob
Qisqa javob: ikkalasi ham "kichik bosqichlarni ulash" va "ma'lumotni oqim sifatida uzatish" g'oyasiga asoslangan. Farqi — Unix'da bosqichlar alohida jarayonlar va ma'lumot baytlar sifatida parallel oqadi; Python generatorlarida esa bosqichlar bitta jarayondagi funksiyalar, ma'lumot obyektlar sifatida navbat bilan (tortib olish orqali) uzatiladi. sort esa ikkalasida ham butun oqimni ko'rmasdan ishlay olmaydi.
1. O'xshashliklar
| Jihat | Unix quvuri | Generator quvuri |
|---|---|---|
| Bosqich | Bitta ish qiladigan dastur | Bitta ish qiladigan generator |
| Ulash | a | b | c |
c(b(a())) |
| Oqim | Qatorma-qator | Elementma-element |
| Xotira | Bufer hajmida | Bitta element |
| Erta to'xtash | head yopilsa, oldingilar SIGPIPE oladi |
Yakunlovchi to'xtasa, generatorlar to'xtab qoladi |
Ikkalasida ham "kichik, bir ishni yaxshi bajaradigan qismlar" falsafasi (Unix falsafasi) ishlaydi.
2. Tub farqlar
a) Bir vaqtda ishlash.
Unix'da cat, grep, sort, head — to'rtta alohida jarayon va ular bir vaqtda ishlaydi. cat o'qiyotganda grep allaqachon filtrlayapti — ko'p yadroli protsessordan foydalanadi.
Generator quvuri esa bitta ipda ishlaydi: yakunlovchi next() so'raydi, bu so'rov zanjir bo'ylab manbagacha boradi, bitta element qaytadi. Hech qachon ikki bosqich bir vaqtda ishlamaydi.
b) Itarish va tortish (push vs pull).
- Unix — itarish:
catimkoni boricha tez yozadi, bufer to'lsa (odatda 64 KB) kutadi - Generator — tortish: hech kim so'ramasa, manba hech narsa qilmaydi
Shuning uchun generatorda "orqaga bosim" (backpressure) muammosi umuman yo'q — tez manba sekin iste'molchini "bosib ketolmaydi".
c) Ma'lumot turi.
Unix quvurida faqat baytlar oqadi. Har bosqich matnni qayta tahlil qiladi — sana, raqam, ustunlar har safar satrdan qayta ajratiladi.
Generatorda obyektlar oqadi: bir marta tahlil qilingan Sotuv obyekti keyingi bosqichlarga tayyor holda uzatiladi. Bu tezroq va xatolarga kamroq moyil.
d) Xatolar.
Unix'da bosqich yiqilsa, qolganlari ko'pincha davom etadi va $? faqat oxirgisining kodini beradi (set -o pipefail bo'lmasa). Xato jimgina yo'qolishi mumkin.
Generatorda xato istisno bo'lib yakunlovchigacha ko'tariladi — traceback butun zanjirni ko'rsatadi.
e) Resurslar.
Unix jarayonlari xotirani izolyatsiya qiladi. Generatorlar bitta jarayon xotirasini bo'lishadi — bosqichlar orasida katta obyektlarni nusxalamasdan uzatish mumkin.
3. Nega sort ikkalasida ham muammo
sort birinchi qatorni chiqarishdan oldin eng kichik qator qaysi ekanini bilishi kerak — buning uchun esa hamma qatorlarni ko'rishi shart. Bu matematik zaruriyat: istalgan saralash algoritmi oxirgi elementni ko'rmaguncha birinchi o'rinni kafolatlay olmaydi.
Oqibatlar:
head -1010 ta qatordan keyin to'xtaydi, lekinsortbaribir butun faylni o'qib bo'lgan- Erta to'xtash foydasi yo'qoladi
- Xotira: GNU
sortkatta faylni vaqtinchalik fayllarga bo'lib, tashqi saralash qiladi; Python'dagisorted()esa hammasini operativ xotiraga yig'adi
4. Yechimlar
a) Aslida saralash kerak emas — faqat eng yaxshi N ta.
sort -k6 -n log | tail -10 # butun oqim saralanadiheapq.nlargest(10, oqim, key=...) # O(n log 10) vaqt, O(10) xotiraKo'p "saralash" vazifalari aslida "top-N" vazifasi. Python'da heapq.nlargest buni bitta o'tishda qiladi.
b) Manba allaqachon saralangan.
Loglar vaqt bo'yicha yoziladi. Bir nechta saralangan oqimni birlashtirish uchun saralash emas, heapq.merge kerak (Misol 4) — u ham to'liq dangasa.
c) Guruhlash uchun saralash.
sort | uniq -c va sorted + groupby o'rniga collections.Counter yoki defaultdict — xotira noyob kalitlar soniga bog'liq bo'ladi, oqim uzunligiga emas.
d) Haqiqatan to'liq saralash kerak bo'lsa — tashqi saralash: oqimni bo'laklab, har bo'lakni saralab, vaqtinchalik fayllarga yozish va heapq.merge bilan birlashtirish. GNU sort aynan shunday ishlaydi.
5. Python'da haqiqiy parallel quvur
Bosqichlar og'ir hisoblash qilsa va parallellik kerak bo'lsa, generatorlar yetmaydi. Unda:
concurrent.futures+ navbatlar (14-qism)multiprocessingbilan jarayonlar quvuri- asinxron generatorlar (
async for) — I/O kutish uchun
Lekin bu murakkablik qo'shadi. Ko'p amaliy vazifalarda asosiy tor joy xotira bo'ladi, parallellik emas. Oddiy generator quvuri esa aynan xotira muammosini hal qiladi.
6. Xulosa
- O'xshash: kichik bosqichlar, oqim sifatida uzatish, erta to'xtash
- Farq: Unix — parallel jarayonlar, baytlar, itarish; generator — bitta ip, obyektlar, tortish
- Tortish modeli orqaga bosim muammosini yo'q qiladi, lekin ko'p yadrodan foydalanmaydi
sortikkalasida ham butun oqimni ko'rishi shart — bu algoritmik zaruriyat- Ko'pincha saralash o'rniga
heapq.nlargest,heapq.mergeyokiCounteryetadi
Nimani mustahkamlaydi: 2.1–2.8-bo'limlar.
Xulosa
Bu darsda generatorlarni real vazifalarda ishlatishni o'rgandik.
Eng muhim uch fikr:
Generator quvuri — manba, oraliq bosqichlar va yakunlovchi. Quvur qurilganda hech narsa bajarilmaydi, yakunlovchi elementlarni tortib ola boshlaganda esa har element butun zanjirdan birma-bir o'tadi. Shuning uchun xotirada bir vaqtda bitta element turadi va yakunlovchi to'xtasa, manba ham o'qishni to'xtatadi. Yon ta'sirli ishni generator emas, oddiy yakunlovchi funksiya bajarsin.
itertoolsvaheapq— tayyor quvur bosqichlari, lekin ikki tuzoq bor.islice,takewhile,chain.from_iterable,pairwise,batched,heapq.mergevaheapq.nlargestquvurni to'liq dangasa saqlaydi.groupbyfaqat yonma-yon elementlarni guruhlaydi va guruhlarini darhol iste'mol qilishni talab qiladi;teeesa orqada qolgan nusxa uchun elementlarni xotirada saqlaydi — ko'pincha bitta o'tishda hisoblash yaxshiroq.Dangasalik xatolarni kechiktiradi — ularni bosqich ichida boshqaring. Buzuq yozuvni o'sha bosqichda ushlab, alohida ro'yxatga yig'ish butun quvurni to'xtatmaydi va hisobotda nechta xato bo'lganini ko'rsatadi. Ma'lumot kichik bo'lsa esa ro'yxat soddaroq: generator xotira va erta to'xtash uchun kerak.
Keyingi darsda yield from bilan tanishamiz: bir generator ishni boshqasiga qanday topshiradi, qaytish qiymati qanday olinadi va send()/throw() zanjir bo'ylab qanday uzatiladi.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!