Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Dangasalik va bir martalik iteratorlar
- 2.2. Cheksiz iteratorlar
- 2.3. islice
- 2.4. Birlashtirish va paketlash
- 2.5. Filtrlash
- 2.6. accumulate
- 2.7. groupby
- 2.8. tee
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Dangasalik va bir martalik iteratorlar
- Misol 2 — Kesish, birlashtirish va filtrlash
- Misol 3 — accumulate, groupby, tee
- Misol 4 — Amaliy: millionlab qatorli jurnalni oqim bilan qayta ishlash
- 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
15.8-dars: itertools: asosiy
15-QISM — STANDART KUTUBXONA · 8-dars
1. Kirish va motivatsiya
9-qismda iterator va generatorlarni o'rgandik: ular elementlarni bittadan, so'ralganda beradi. itertools moduli shu g'oyaning "asboblar qutisi": iteratorlarni kesish, birlashtirish, guruhlash, yig'ish va paketlash uchun C da yozilgan tez va dangasa qurilmalar.
Real vaziyat. Jamoa kunlik jurnal faylini (12 GB) tahlil qilardi:
qatorlar = open(yol).readlines() # butun fayl xotiraga
xatolar = [q for q in qatorlar if "ERROR" in q]
birinchi_100 = xatolar[:100]Server 8 GB xotiraga ega edi — skript MemoryError bilan yiqildi. Xuddi shu vazifa dangasa quvur bilan bir necha megabayt xotirada ishlaydi:
with open(yol) as f:
xatolar = (q for q in f if "ERROR" in q)
birinchi_100 = list(itertools.islice(xatolar, 100)) # 100 ta topilgach — to'xtaydiLekin dangasalikning o'z tuzoqlari bor: iterator bir marta o'qiladi, groupby saralanmagan ma'lumotda "noto'g'ri" guruhlaydi, in tekshiruvi elementlarni iste'mol qiladi. Bu darsda ikkalasini ham ko'ramiz.
Bu darsda:
- Dangasalik va bir martalik iteratorlar
- Cheksiz iteratorlar:
count,cycle,repeat -
islice— iteratorni kesish chain,zip_longest,pairwise,batched- Filtrlash:
takewhile,dropwhile,filterfalse,compress -
accumulate— yig'ilib boruvchi natijalar -
groupby— faqat ketma-ket kelganlar tee— iteratorni ikkiga bo'lish va uning narxi- Amaliy: millionlab qatorli jurnalni oqim bilan qayta ishlash
2. Nazariya — chuqur tushuntirish
2.1. Dangasalik va bir martalik iteratorlar
itertools funksiyalari iterator qaytaradi: hech narsa hisoblamaydi, faqat next() so'ralganda bitta element beradi.
| Obyekt | Qayta o'qish mumkinmi |
|---|---|
list, tuple, range, str |
Har safar yangi iterator |
Generator, map, filter, zip |
Bir marta |
itertools.* natijalari |
Bir marta |
| Ochilgan fayl | Bir marta (oxirigacha o'qilgach) |
g = (x for x in range(3))
list(g) # [0, 1, 2]
list(g) # [] — jim bo'sh in ham iteratorni iste'mol qiladi:
it = iter([1, 2, 3, 4])
2 in it # True — lekin 1 va 2 o'qib bo'lindi
list(it) # [3, 4]| Afzallik | Narxi |
|---|---|
Xotira — O(1) |
Qayta o'qib bo'lmaydi |
| Cheksiz ketma-ketliklar | len(), indeks, kesma yo'q |
| Erta to'xtash | Xato kechroq ko'rinadi (dangasa) |
2.2. Cheksiz iteratorlar
| Funksiya | Natija |
|---|---|
count(boshi=0, qadam=1) |
0, 1, 2, ... |
cycle(it) |
a, b, a, b, ... |
repeat(x, n=None) |
x, x, x, ... (yoki n marta) |
Cheksiz iteratorni list() ga bermang — xotira tugaguncha ishlaydi. Doim islice, zip yoki takewhile bilan chegaralang.
2.3. islice
islice(it, stop)
islice(it, start, stop, step)| Xususiyat | seq[a:b:c] |
islice(it, a, b, c) |
|---|---|---|
| Istalgan iterable | Faqat ketma-ketlik | |
| Manfiy indeks | ValueError |
|
| Xotira | Nusxa yaratadi | Dangasa |
| Boshlanishgacha | To'g'ridan-to'g'ri | start gacha elementlar o'qib tashlanadi |
2.4. Birlashtirish va paketlash
| Funksiya | Natija |
|---|---|
chain(a, b) |
a elementlari, keyin b |
chain.from_iterable(ichma_ich) |
Bir daraja tekislash — dangasa |
zip(a, b, strict=True) |
Uzunliklar teng bo'lmasa ValueError (3.10+) |
zip_longest(a, b, fillvalue=x) |
Eng uzunigacha, bo'sh joylar x |
pairwise(it) |
(a0, a1), (a1, a2), ... (3.10+) |
batched(it, n) |
n talik kortejlar, oxirgisi qisqa bo'lishi mumkin (3.12+) |
batched(it, n, strict=True) |
Oxirgisi to'liq bo'lmasa ValueError (3.13+) |
starmap(f, juftlar) |
f(*juft) |
batched — bazaga paketlab yozish, API ga bo'lib yuborishning standart vositasi.
2.5. Filtrlash
| Funksiya | Qachon to'xtaydi / nima qiladi |
|---|---|
filter(shart, it) |
Shart bajarilganlarini beradi |
filterfalse(shart, it) |
Shart bajarilmaganlarini |
takewhile(shart, it) |
Shart birinchi marta bajarilmaguncha — keyin to'xtaydi |
dropwhile(shart, it) |
Shart bajarilguncha tashlaydi, keyin hammasini beradi |
compress(it, belgilar) |
belgilar[i] rost bo'lganlarini |
list(takewhile(lambda x: x < 3, [1, 2, 5, 1])) # [1, 2] — oxirgi 1 kelmaydi
list(dropwhile(lambda x: x < 3, [1, 2, 5, 1])) # [5, 1] — 1 ham qaytadi takewhile shart bajarilmagan birinchi elementni ham iste'mol qiladi — u yo'qoladi.
2.6. accumulate
accumulate([1, 2, 3, 4]) # 1, 3, 6, 10 — yig'indi
accumulate([1, 2, 3, 4], operator.mul) # 1, 2, 6, 24 — ko'paytma
accumulate([3, 1, 4, 1, 5], max) # 3, 3, 4, 4, 5 — shu paytgacha maksimum
accumulate([1, 2, 3], initial=100) # 100, 101, 103, 106Qo'llanishlar: kumulyativ tushum, hisob qoldig'i, "rekord" qiymatlar, prefiks yig'indilar (oraliq yig'indisini O(1) da hisoblash).
2.7. groupby
groupby(it, key) — ketma-ket kelgan bir xil kalitli elementlarni guruhlaydi. U SQL GROUP BY emas.
sozlar = ["olma", "anor", "olcha"]
[(k, list(g)) for k, g in groupby(sozlar, key=lambda s: s[0])]
# [('o', ['olma']), ('a', ['anor']), ('o', ['olcha'])] — 'o' ikki marta!
[(k, list(g)) for k, g in groupby(sorted(sozlar), key=lambda s: s[0])]
# [('a', ['anor']), ('o', ['olcha', 'olma'])]| Tuzoq | Yechim |
|---|---|
| Ma'lumot saralanmagan | Avval sorted(..., key=bir_xil_kalit) yoki defaultdict(list) (15.6) |
| Guruhlar keyinroq o'qiladi | list(groupby(...)) — guruhlar bo'shab qoladi; har guruhni darhol list(g) qiling |
| Saralash kaliti ≠ guruhlash kaliti | Bir xil kalit funksiyasi |
| Vosita | Xotira | Saralash kerakmi | Qachon |
|---|---|---|---|
groupby |
O(1) (bitta guruh) |
Oqim allaqachon tartiblangan (vaqt, fayl) | |
defaultdict(list) |
O(n) |
Tartibsiz ma'lumot |
2.8. tee
tee(it, n=2) — bitta iteratordan n ta mustaqil iterator.
Narxi: bir nusxa oldinda ketsa, ikkinchisi uchun o'qilgan elementlar buferda saqlanadi. Biri oxirigacha o'qilsa — hammasi xotirada. tee dan keyin asl iteratorni ishlatmang.
Ikki marta o'qish kerak va ma'lumot kichik bo'lsa — list oddiyroq va tezroq.
3. Tez ma'lumotnoma
import itertools as it
import operator
it.islice(oqim, 100) # birinchi 100 ta
it.chain.from_iterable(royxatlar) # tekislash
it.batched(yozuvlar, 1000) # 1000 talik paketlar
it.pairwise(vaqtlar) # qo'shni juftliklar
it.accumulate(summalar) # kumulyativ yig'indi
for kalit, guruh in it.groupby(sorted(xs, key=f), key=f):
elementlar = list(guruh) # darhol
it.takewhile(lambda q: q.startswith("#"), qatorlar)Qoidalar
iterator bir martalik — kerak bo'lsa list()
in ham iteratorni iste'mol qiladi
cheksiz iterator — doim chegara bilan
groupby — faqat ketma-ket; avval sorted
groupby guruhini darhol o'qing
tee — faqat yaqin yurgan nusxalar uchun4. Batafsil misollar
Misol 1 — Dangasalik va bir martalik iteratorlar
"""Generator, zip, map bir martalik; in iste'mol qiladi; range qayta o'qiladi; dangasa quvur tartibi; cheksiz iteratorlar; xotira."""
import itertools as it
import sys
def main() -> None:
print("=== 1. ⚠️ Bir martalik ===")
g = (x * x for x in range(4))
print(f" generator: {list(g)}, qayta: {list(g)}")
z = zip("ab", [1, 2])
print(f" zip: {list(z)}, qayta: {list(z)}")
r = range(3)
print(f" range: {list(r)}, qayta: {list(r)}")
print("\n=== 2. ⚠️ in iteratorni iste'mol qiladi ===")
raqamlar = iter([1, 2, 3, 4, 5])
print(f" 3 in raqamlar: {3 in raqamlar}")
print(f" qolgani: {list(raqamlar)}")
sonlar = map(int, "12345")
print(f" sum(map) = {sum(sonlar)}, keyin max(default=None): {max(sonlar, default=None)}")
print("\n=== 3. Dangasa quvur: nima qachon bajariladi ===")
jurnal: list[str] = []
def manba():
for i in range(1, 6):
jurnal.append(f"o'qildi {i}")
yield i
juftlar = (x for x in manba() if x % 2 == 0)
kvadratlar = (x * x for x in juftlar)
print(f" quvur qurildi, jurnal: {jurnal}")
birinchisi = next(kvadratlar)
print(f" next() = {birinchisi}, jurnal: {jurnal}")
print(" ⭐ faqat birinchi natija uchun kerak bo'lgan elementlar o'qildi")
print("\n=== 4. Cheksiz iteratorlar ===")
print(f" count(10, 5): {list(it.islice(it.count(10, 5), 4))}")
print(f" cycle('KQS'): {''.join(it.islice(it.cycle('KQS'), 7))}")
print(f" repeat('-', 5): {''.join(it.repeat('-', 5))}")
navbatchilar = ["Aziz", "Malika", "Bek"]
kunlar = ["du", "se", "chor", "pay", "ju"]
print(f" navbatchilik: {list(zip(kunlar, it.cycle(navbatchilar)))}")
print("\n=== 5. Xotira ===")
royxat = list(range(1_000_000))
dangasa = it.islice(it.count(), 1_000_000)
print(f" 1 mln elementli list: {sys.getsizeof(royxat) // 1024} KB")
print(f" islice(count()): {sys.getsizeof(dangasa)} bayt")
print(f" natijalar yig'indisi teng: {sum(royxat) == sum(dangasa)}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. ⚠️ Bir martalik ===
generator: [0, 1, 4, 9], qayta: []
zip: [('a', 1), ('b', 2)], qayta: []
range: [0, 1, 2], qayta: [0, 1, 2]
=== 2. ⚠️ in iteratorni iste'mol qiladi ===
3 in raqamlar: True
qolgani: [4, 5]
sum(map) = 15, keyin max(default=None): None
=== 3. Dangasa quvur: nima qachon bajariladi ===
quvur qurildi, jurnal: []
next() = 4, jurnal: ["o'qildi 1", "o'qildi 2"]
⭐ faqat birinchi natija uchun kerak bo'lgan elementlar o'qildi
=== 4. Cheksiz iteratorlar ===
count(10, 5): [10, 15, 20, 25]
cycle('KQS'): KQSKQSK
repeat('-', 5): -----
navbatchilik: [('du', 'Aziz'), ('se', 'Malika'), ('chor', 'Bek'), ('pay', 'Aziz'), ('ju', 'Malika')]
=== 5. Xotira ===
1 mln elementli list: 7812 KB
islice(count()): 72 bayt
natijalar yig'indisi teng: TrueNima ko'rsatdi: 2.1, 2.2-bo'limlar.
Misol 2 — Kesish, birlashtirish va filtrlash
"""islice va uning cheklovlari; chain va from_iterable; zip strict va zip_longest; pairwise; batched va strict; takewhile, dropwhile, filterfalse, compress."""
import itertools as it
def main() -> None:
print("=== 1. islice ===")
print(f" islice(range(10), 2, 8, 3): {list(it.islice(range(10), 2, 8, 3))}")
print(f" fayl kabi oqimdan 3 ta: {list(it.islice(iter(['a', 'b', 'c', 'd']), 3))}")
try:
it.islice(range(10), -3, None)
except ValueError:
print(" islice(..., -3) → ValueError: manfiy indeks yo'q")
print("\n=== 2. chain ===")
guruhlar = [["Aziz", "Bek"], ["Malika"], [], ["Nodira", "Sardor"]]
print(f" chain(*guruhlar): {list(it.chain(*guruhlar))}")
print(f" chain.from_iterable(guruhlar): {list(it.chain.from_iterable(guruhlar))}")
print("\n=== 3. zip, zip_longest ===")
ismlar, ballar = ["Aziz", "Bek", "Malika"], [87, 92]
print(f" zip: {list(zip(ismlar, ballar))} ← Malika jim yo'qoldi")
try:
list(zip(ismlar, ballar, strict=True))
except ValueError as xato:
print(f" strict=True: ValueError: {xato}")
print(f" zip_longest: {list(it.zip_longest(ismlar, ballar, fillvalue=None))}")
print("\n=== 4. pairwise ===")
narxlar = [12_000, 12_500, 12_100, 13_000, 13_000]
ozgarish = [b - a for a, b in it.pairwise(narxlar)]
print(f" narxlar: {narxlar}")
print(f" kunlik o'zgarish: {ozgarish}")
print("\n=== 5. batched ===")
print(f" batched(range(7), 3): {list(it.batched(range(7), 3))}")
try:
list(it.batched(range(7), 3, strict=True))
except ValueError as xato:
print(f" strict=True: ValueError: {xato}")
print("\n=== 6. Filtrlash ===")
fayl = ["# sozlamalar", "# muallif: Wisar", "host=localhost", "# izoh", "port=5432"]
print(f" takewhile (sarlavha): {list(it.takewhile(lambda q: q.startswith('#'), fayl))}")
print(f" dropwhile (qolgani): {list(it.dropwhile(lambda q: q.startswith('#'), fayl))}")
print(f" filterfalse (izohsiz): {list(it.filterfalse(lambda q: q.startswith('#'), fayl))}")
print(f" compress: {list(it.compress(['du', 'se', 'chor', 'pay', 'ju'], [1, 0, 1, 0, 1]))}")
print("\n=== 7. ⚠️ takewhile bitta elementni yutadi ===")
oqim = iter([1, 2, 5, 3, 4])
kichiklar = list(it.takewhile(lambda x: x < 3, oqim))
print(f" takewhile: {kichiklar}, oqimda qolgani: {list(oqim)} ← 5 yo'qoldi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. islice ===
islice(range(10), 2, 8, 3): [2, 5]
fayl kabi oqimdan 3 ta: ['a', 'b', 'c']
islice(..., -3) → ValueError: manfiy indeks yo'q
=== 2. chain ===
chain(*guruhlar): ['Aziz', 'Bek', 'Malika', 'Nodira', 'Sardor']
chain.from_iterable(guruhlar): ['Aziz', 'Bek', 'Malika', 'Nodira', 'Sardor']
=== 3. zip, zip_longest ===
zip: [('Aziz', 87), ('Bek', 92)] ← Malika jim yo'qoldi
strict=True: ValueError: zip() argument 2 is shorter than argument 1
zip_longest: [('Aziz', 87), ('Bek', 92), ('Malika', None)]
=== 4. pairwise ===
narxlar: [12000, 12500, 12100, 13000, 13000]
kunlik o'zgarish: [500, -400, 900, 0]
=== 5. batched ===
batched(range(7), 3): [(0, 1, 2), (3, 4, 5), (6,)]
strict=True: ValueError: batched(): incomplete batch
=== 6. Filtrlash ===
takewhile (sarlavha): ['# sozlamalar', '# muallif: Wisar']
dropwhile (qolgani): ['host=localhost', '# izoh', 'port=5432']
filterfalse (izohsiz): ['host=localhost', 'port=5432']
compress: ['du', 'chor', 'ju']
=== 7. ⚠️ takewhile bitta elementni yutadi ===
takewhile: [1, 2], oqimda qolgani: [3, 4] ← 5 yo'qoldiNima ko'rsatdi: 2.3, 2.4, 2.5-bo'limlar.
Misol 3 — accumulate, groupby, tee
"""accumulate: yig'indi, maksimum, initial, prefiks yig'indilar; groupby: saralanmagan tuzog'i, guruhlarni kech o'qish tuzog'i, defaultdict bilan solishtirish; tee buferi."""
import itertools as it
import operator
from collections import defaultdict
def main() -> None:
print("=== 1. accumulate ===")
tushum = [120, 80, 150, 90, 200]
print(f" kunlik: {tushum}")
print(f" kumulyativ: {list(it.accumulate(tushum))}")
print(f" rekordlar: {list(it.accumulate(tushum, max))}")
print(f" ko'paytma: {list(it.accumulate([1, 2, 3, 4], operator.mul))}")
print(f" boshlang'ich 500: {list(it.accumulate([-120, 300, -50], initial=500))}")
prefiks = list(it.accumulate(tushum, initial=0))
print(f" prefiks yig'indi: {prefiks}")
print(f" 2..4-kunlar yig'indisi O(1): {prefiks[5] - prefiks[1]} (tekshiruv: {sum(tushum[1:5])})")
print("\n=== 2. ⚠️ groupby saralanmagan ma'lumotda ===")
mevalar = ["olma", "anor", "banan", "behi", "olcha", "avakado"]
birinchi_harf = operator.itemgetter(0)
xato = [(k, list(g)) for k, g in it.groupby(mevalar, key=birinchi_harf)]
togri = [(k, list(g)) for k, g in it.groupby(sorted(mevalar, key=birinchi_harf), key=birinchi_harf)]
print(f" saralanmagan: {xato}")
print(f" saralangan: {togri}")
print("\n=== 3. ⚠️ Guruhni kech o'qish ===")
guruhlar = list(it.groupby("aaabbc"))
print(f" list(groupby(...)) keyin: {[(k, list(g)) for k, g in guruhlar]} ← guruhlar bo'sh")
darhol = [(k, len(list(g))) for k, g in it.groupby("aaabbc")]
print(f" darhol o'qilganda: {darhol}")
print("\n=== 4. Ketma-ketliklarni siqish (run-length) ===")
signal = "AAAABBBCCDAA"
siqilgan = "".join(f"{k}{len(list(g))}" for k, g in it.groupby(signal))
print(f" {signal} → {siqilgan}")
print(" ⭐ bu yerda aynan ketma-ketlik kerak — saralash xato bo'lardi")
print("\n=== 5. groupby va defaultdict ===")
buyurtmalar = [("2026-09-15", 120), ("2026-09-15", 80), ("2026-09-16", 200), ("2026-09-15", 50)]
oqim_boyicha = {k: sum(s for _, s in g) for k, g in it.groupby(buyurtmalar, key=operator.itemgetter(0))}
lugat: defaultdict[str, int] = defaultdict(int)
for kun, summa in buyurtmalar:
lugat[kun] += summa
print(f" groupby (saralanmagan): {oqim_boyicha} ← 15-sentabr qayta yozildi")
print(f" defaultdict: {dict(lugat)}")
print("\n=== 6. tee ===")
a, b = it.tee(iter([1, 2, 3]))
print(f" a: {list(a)}, b: {list(b)}")
oldingi, keyingi = it.tee(iter(range(5)))
next(keyingi, None)
qolda = list(zip(oldingi, keyingi))
print(f" qo'lda pairwise: {qolda}")
print(f" itertools.pairwise bilan bir xil: {qolda == list(it.pairwise(range(5)))}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. accumulate ===
kunlik: [120, 80, 150, 90, 200]
kumulyativ: [120, 200, 350, 440, 640]
rekordlar: [120, 120, 150, 150, 200]
ko'paytma: [1, 2, 6, 24]
boshlang'ich 500: [500, 380, 680, 630]
prefiks yig'indi: [0, 120, 200, 350, 440, 640]
2..4-kunlar yig'indisi O(1): 520 (tekshiruv: 520)
=== 2. ⚠️ groupby saralanmagan ma'lumotda ===
saralanmagan: [('o', ['olma']), ('a', ['anor']), ('b', ['banan', 'behi']), ('o', ['olcha']), ('a', ['avakado'])]
saralangan: [('a', ['anor', 'avakado']), ('b', ['banan', 'behi']), ('o', ['olma', 'olcha'])]
=== 3. ⚠️ Guruhni kech o'qish ===
list(groupby(...)) keyin: [('a', []), ('b', []), ('c', [])] ← guruhlar bo'sh
darhol o'qilganda: [('a', 3), ('b', 2), ('c', 1)]
=== 4. Ketma-ketliklarni siqish (run-length) ===
AAAABBBCCDAA → A4B3C2D1A2
⭐ bu yerda aynan ketma-ketlik kerak — saralash xato bo'lardi
=== 5. groupby va defaultdict ===
groupby (saralanmagan): {'2026-09-15': 50, '2026-09-16': 200} ← 15-sentabr qayta yozildi
defaultdict: {'2026-09-15': 250, '2026-09-16': 200}
=== 6. tee ===
a: [1, 2, 3], b: [1, 2, 3]
qo'lda pairwise: [(0, 1), (1, 2), (2, 3), (3, 4)]
itertools.pairwise bilan bir xil: TrueNima ko'rsatdi: 2.6, 2.7, 2.8-bo'limlar.
Misol 4 — Amaliy: millionlab qatorli jurnalni oqim bilan qayta ishlash
Kirishdagi vaziyat: katta jurnal faylini xotiraga yuklamasdan qayta ishlaymiz. Jurnal generator bilan hosil qilinadi (1 000 000 qator — faylni o'qishning o'zi kabi dangasa). Quvur: ERROR qatorlarni ajratish, birinchi 3 tasini ko'rish, daqiqalar bo'yicha guruhlash (jurnal vaqt bo'yicha tartiblangan — groupby ideal), xatolar orasidagi eng uzun tanaffus (pairwise), bazaga 50 000 talik paketlar (batched). Oxirida xotira sarfini tracemalloc bilan ro'yxat usuli bilan solishtiramiz.
"""Dangasa quvur: generator manba, filter, islice, groupby, pairwise, batched, accumulate; tracemalloc bilan xotira solishtiruvi."""
import itertools as it
import tracemalloc
from collections.abc import Iterator
QATORLAR = 1_000_000
def jurnal() -> Iterator[str]:
"""Faylni satrma-satr o'qishni taqlid qiladi: har 1 soniyada bitta yozuv."""
for i in range(QATORLAR):
kun, qoldiq = divmod(i, 86_400)
soat, qoldiq = divmod(qoldiq, 3600)
daqiqa, soniya = divmod(qoldiq, 60)
daraja = "ERROR" if (i % 997 == 0 or 500_000 <= i < 500_020) else "INFO"
yield f"2026-09-{17 + kun:02d}T{soat:02d}:{daqiqa:02d}:{soniya:02d} {daraja} so'rov={i}"
def soniya(qator: str) -> int:
kun = int(qator[8:10]) - 17
s, d, c = qator[11:19].split(":")
return kun * 86_400 + int(s) * 3600 + int(d) * 60 + int(c)
def xatolar(qatorlar: Iterator[str]) -> Iterator[str]:
return (q for q in qatorlar if " ERROR " in q)
def quvur() -> dict[str, object]:
natija: dict[str, object] = {}
natija["birinchi_3"] = [q.split()[-1] for q in it.islice(xatolar(jurnal()), 3)]
daqiqalar = it.groupby(xatolar(jurnal()), key=lambda q: q[:16])
zich = max(((kalit, sum(1 for _ in guruh)) for kalit, guruh in daqiqalar), key=lambda kg: kg[1])
natija["eng_zich_daqiqa"] = zich
vaqtlar = (soniya(q) for q in xatolar(jurnal()))
tanaffus = max(b - a for a, b in it.pairwise(vaqtlar))
natija["eng_uzun_tanaffus_s"] = tanaffus
paketlar = it.batched(xatolar(jurnal()), 500)
hajmlar = [len(p) for p in paketlar]
natija["paketlar"] = (len(hajmlar), hajmlar[-1])
natija["jami_xato"] = list(it.accumulate(hajmlar))[-1]
return natija
def royxat_usuli() -> int:
qatorlar = list(jurnal())
return len([q for q in qatorlar if " ERROR " in q])
def main() -> None:
tracemalloc.start()
natija = quvur()
_, quvur_cho_qqisi = tracemalloc.get_traced_memory()
tracemalloc.reset_peak()
royxat_natija = royxat_usuli()
_, royxat_cho_qqisi = tracemalloc.get_traced_memory()
tracemalloc.stop()
print(f"=== 1. {QATORLAR:_} qatorli jurnal ===".replace("_", " "))
print(f" birinchi 3 xato: {natija['birinchi_3']}")
print(f" eng zich daqiqa: {natija['eng_zich_daqiqa']}")
print(f" xatolar orasidagi eng uzun tanaffus: {natija['eng_uzun_tanaffus_s']} s")
print(f" 500 talik paketlar: {natija['paketlar'][0]} ta, oxirgisi {natija['paketlar'][1]} ta yozuv")
print(f" jami xato: {natija['jami_xato']}")
print("\n=== 2. Tekshiruvlar ===")
print(f" ro'yxat usuli bilan bir xil son: {natija['jami_xato'] == royxat_natija}")
kutilgan = len({i for i in range(QATORLAR) if i % 997 == 0} | set(range(500_000, 500_020)))
print(f" formula bo'yicha kutilgan: {natija['jami_xato'] == kutilgan}")
print("\n=== 3. Xotira (tracemalloc cho'qqisi) ===")
print(f" quvur 1 MB dan kam: {quvur_cho_qqisi < 1_000_000}")
print(f" ro'yxat usuli 50 MB dan ko'p: {royxat_cho_qqisi > 50_000_000}")
print(f" farq kamida 100 barobar: {royxat_cho_qqisi / quvur_cho_qqisi >= 100}")
print("\n=== 4. Qoidalar ===")
print(" ✅ manba — generator (fayl ham shunday o'qiladi)")
print(" ✅ har tahlil uchun yangi quvur — iterator bir martalik")
print(" ✅ groupby — jurnal vaqt bo'yicha tartiblangani uchun saralashsiz")
print(" ✅ islice — kerakli miqdor topilgach, o'qish to'xtaydi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. 1 000 000 qatorli jurnal ===
birinchi 3 xato: ["so'rov=0", "so'rov=997", "so'rov=1994"]
eng zich daqiqa: ('2026-09-22T18:53', 20)
xatolar orasidagi eng uzun tanaffus: 997 s
500 talik paketlar: 3 ta, oxirgisi 24 ta yozuv
jami xato: 1024
=== 2. Tekshiruvlar ===
ro'yxat usuli bilan bir xil son: True
formula bo'yicha kutilgan: True
=== 3. Xotira (tracemalloc cho'qqisi) ===
quvur 1 MB dan kam: True
ro'yxat usuli 50 MB dan ko'p: True
farq kamida 100 barobar: True
=== 4. Qoidalar ===
✅ manba — generator (fayl ham shunday o'qiladi)
✅ har tahlil uchun yangi quvur — iterator bir martalik
✅ groupby — jurnal vaqt bo'yicha tartiblangani uchun saralashsiz
✅ islice — kerakli miqdor topilgach, o'qish to'xtaydiNima ko'rsatdi: 2.1, 2.3, 2.4, 2.6, 2.7-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Generatorni ikki marta aylanish mumkin" | Ikkinchi marta bo'sh |
"x in iterator iteratorni o'zgartirmaydi" |
Topilgunicha elementlarni iste'mol qiladi |
"groupby — SQL GROUP BY" |
Faqat ketma-ket kelganlarni |
"groupby guruhlarini keyin o'qish mumkin" |
Keyingi guruhga o'tilgach bo'shaydi |
"islice manfiy indeksni qo'llaydi" |
ValueError |
"takewhile hech narsani yo'qotmaydi" |
Shartga to'g'ri kelmagan birinchi elementni yutadi |
"zip uzunliklar farqini xabar qiladi" |
Jim qisqartiradi — strict=True |
"tee bepul nusxa" |
O'qilmagan elementlar buferda saqlanadi |
6. Keng tarqalgan xatolar va yechimlari
1. Iteratorni ikki marta ishlatish
sozlar = (s.strip() for s in f)
jami = sum(1 for _ in sozlar); noyob = set(sozlar) # ❌ noyob — bo'sh
sozlar = [s.strip() for s in f] # ✅ kichik bo'lsa — list2. Saralanmagan groupby
groupby(buyurtmalar, key=kun) # ❌
groupby(sorted(buyurtmalar, key=kun), key=kun) # ✅3. Guruhlarni saqlab qo'yish
guruhlar = list(groupby(xs, key=f)) # ❌ guruhlar bo'shaydi
guruhlar = [(k, list(g)) for k, g in groupby(xs, key=f)] # ✅4. Cheksiz iteratorni to'liq o'qish
list(itertools.count()) # ❌ xotira tugaydi
list(itertools.islice(itertools.count(), 10)) # ✅5. Uzunlik farqini yashirish
for ism, ball in zip(ismlar, ballar): ... # ⚠️ jim qisqaradi
for ism, ball in zip(ismlar, ballar, strict=True): ... # ✅6. Qo'lda paketlash
for i in range(0, len(xs), 1000): paket = xs[i:i+1000] # ⚠️ faqat list uchun
for paket in itertools.batched(oqim, 1000): ... # ✅ istalgan iterator7. Katta faylni readlines
qatorlar = f.readlines() # ❌
for qator in f: ... # ✅8. tee va uzoqlashgan nusxalar
a, b = tee(katta_oqim); list(a); list(b) # ⚠️ butun oqim xotirada7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 9-qism (o'tilgan): iterator protokoli va generatorlar
- 11.8-dars (o'tilgan): xotira o'lchash,
tracemalloc - 15.6–15.7-darslar (o'tilgan):
defaultdict,deque - 15.9-dars:
product,permutations,combinations - 15.10-dars:
functools.reduce,partial - 16.8-dars: katta fayllarni oqim bilan o'qish
- 23-qism: bazaga paketlab yozish
- 24-qism: ma'lumot quvurlari va
pandasga o'tish
8. Eng yaxshi amaliyotlar
Katta ma'lumot — dangasa quvur.
Iterator bir martalik ekanini unutmang — har tahlilga yangi quvur yoki
list.groupbydan oldin shu kalit bilan saralang — yoki ma'lumot allaqachon tartiblanganiga ishonch hosil qiling.zip(..., strict=True)— uzunliklar teng bo'lishi kerak bo'lganda.Paketlash —
batched.Cheksiz iteratorlar — doim chegara bilan.
Xotirani o'lchang (
tracemalloc) — dangasalik foydasini taxmin qilmang.O'qilishi muhim — uzun
itertoolszanjirini nomli bosqichlarga bo'ling.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
import itertools as it
1. print(list(it.islice(it.count(5), 3)))
2. print(list(it.accumulate([2, 3, 4])))
3. print(list(it.chain("ab", [1])))
4. print([k for k, _ in it.groupby("aabaa")])
5. print(list(it.takewhile(lambda x: x > 0, [3, 1, 0, 2])))
6. print(list(it.dropwhile(lambda x: x > 0, [3, 1, 0, 2])))
7. print(list(it.pairwise("abc")))
8. print(list(it.batched("abcde", 2)))
9. g = (x for x in [1, 2]); list(g); print(list(g))
10. i = iter([1, 2, 3]); print(2 in i, list(i))
11. print(list(it.zip_longest([1, 2], "a")))
12. print(list(it.compress("xyz", [0, 1, 1])))Javoblar
[5, 6, 7][2, 5, 9]['a', 'b', 1]['a', 'b', 'a'][3, 1][0, 2][('a', 'b'), ('b', 'c')][('a', 'b'), ('c', 'd'), ('e',)][]True [3][(1, 'a'), (2, None)]['y', 'z']
Vazifa 2: Xatolarni tuzating
1. def kunlik_summa(buyurtmalar): # (sana, summa), tartibsiz
return {k: sum(s for _, s in g) for k, g in groupby(buyurtmalar, key=lambda b: b[0])}
2. def statistika(sonlar_generatori):
return sum(sonlar_generatori) / len(list(sonlar_generatori))
3. def birinchi_10_xato(yol):
return [q for q in open(yol).readlines() if "ERROR" in q][:10]
4. def juftla(ismlar, telefonlar):
return dict(zip(ismlar, telefonlar)) # uzunliklar teng bo'lishi shart
5. def guruhlarni_ol(sozlar):
return dict(groupby(sorted(sozlar), key=len))Javoblar
1. def kunlik_summa(buyurtmalar):
kalit = lambda b: b[0]
return {k: sum(s for _, s in g) for k, g in groupby(sorted(buyurtmalar, key=kalit), key=kalit)}
2. def statistika(sonlar_generatori):
sonlar = list(sonlar_generatori) # yoki bitta aylanishda yig'indi va sanoq
return sum(sonlar) / len(sonlar)
3. def birinchi_10_xato(yol):
with open(yol, encoding="utf-8") as f:
return list(islice((q for q in f if "ERROR" in q), 10))
4. def juftla(ismlar, telefonlar):
return dict(zip(ismlar, telefonlar, strict=True))
5. def guruhlarni_ol(sozlar):
return {k: list(g) for k, g in groupby(sorted(sozlar, key=len), key=len)}Vazifa 3: itertools ni qayta yozish
Faqat generatorlar bilan yozing va natijani asl funksiyalar bilan 100 ta tasodifiy kirishda solishtiring:
mening_islice(it, start, stop, step)mening_groupby(it, key)— guruhlarni kech o'qish xulqi ham asl bilan bir xil bo'lsinmening_batched(it, n)mening_pairwise(it)—teesiz- Tezlikni solishtiring va farq sababini tushuntiring
Vazifa 4: Sessiyalar
Foydalanuvchi harakatlari jurnalidan (vaqt bo'yicha tartiblangan (foydalanuvchi, vaqt)):
- Har foydalanuvchi uchun sessiyalarni ajrating: 30 daqiqadan ortiq tanaffus — yangi sessiya (
pairwise+accumulate) - Har sessiya uzunligi va harakatlar soni
- Eng uzun sessiyani toping
- Xotira
O(bitta foydalanuvchi harakatlari)bo'lsin
Vazifa 5: CSV ni paketlab import qilish
- 1 mln qatorli CSV ni satrma-satr o'qing (16-qismdan oldin
str.split(",")bilan) - Sarlavhani
islicebilan ajrating - 10 000 talik paketlarda "bazaga yozing" (ro'yxatga)
- Noto'g'ri qatorlarni
filterfalsebilan alohida faylga tracemallocbilan xotira cho'qqisinireadlines()usuli bilan solishtiring
Vazifa 6: Oqimdagi statistika
Cheksiz sensor oqimi (count + tasodifiy qiymatlar) uchun:
- Har 100 ta o'lchovdan keyin o'rtacha (
batched) - Kumulyativ maksimum (
accumulate(max)) - Qiymat ketma-ket 5 marta chegaradan oshsa — ogohlantirish (
groupby) - Birinchi ogohlantirishgacha o'qing (
takewhile)
Vazifa 7: O'ylash
Python'da map, filter, zip va range Python 2 da ro'yxat qaytarardi, Python 3 da esa dangasa obyekt (range — qayta o'qiladigan, qolganlari — bir martalik iterator). Bu o'zgarish nega qilingan, qanday xatolarni kamaytirdi va qanday yangi xatolarni keltirib chiqardi? Nega range boshqalardan farqli ravishda qayta o'qiladi?
Javob
Qisqa javob: Python 3 dangasalikni sukut qildi: xotira tejaldi, katta va cheksiz ketma-ketliklar bilan ishlash tabiiy bo'ldi. Narxi — "bir martalik" iteratorlar tufayli jim xatolar (ikkinchi aylanishda bo'sh natija). range esa ketma-ketlik (sequence) sifatida qayta ishlab chiqildi: u faqat start, stop, step ni saqlaydi va har iter() da yangi iterator beradi — shuning uchun ham dangasa, ham qayta o'qiladi.
1. Python 2 va 3
| Funksiya | Python 2 | Python 3 |
|---|---|---|
range |
list (xrange — dangasa) |
Dangasa ketma-ketlik |
map, filter |
list (itertools.imap — dangasa) |
Bir martalik iterator |
zip |
list (izip) |
Bir martalik iterator |
dict.keys() |
list |
Ko'rinish (view) — jonli, qayta o'qiladi |
2. Nega o'zgartirildi
- Xotira:
range(10**9)Python 2 da 1 mlrd elementli ro'yxat — imkonsiz - Tezlik:
for x in map(f, xs)— oraliq ro'yxat yaratilmaydi - Birlashuvchanlik: dangasa bosqichlar quvur hosil qiladi, erta to'xtaydi
- Izchillik:
xrange/range,imap/mapkabi ikki xil nomlar yo'qoldi
3. Kamaygan xatolar
MemoryErrorva "sekin" skriptlar- Keraksiz nusxalar (
zip(*...)uchun oraliq ro'yxatlar)
4. Paydo bo'lgan xatolar
| Xato | Belgisi |
|---|---|
| Ikkinchi aylanish bo'sh | Hech qanday istisno yo'q — jim |
len(map(...)) |
TypeError |
in iste'mol qiladi |
Keyingi o'qishda elementlar yetishmaydi |
| Kechiktirilgan xato | Istisno quvur qurilganda emas, o'qilganda chiqadi — traceback boshqa joyda |
| Yopilgan fayl ustidagi generator | ValueError: I/O operation on closed file — with blokidan tashqarida o'qilganda |
5. Nega range qayta o'qiladi
range — iterable ketma-ketlik, iterator emas:
| Xususiyat | range |
map |
|---|---|---|
__iter__ |
Har safar yangi iterator | self ni qaytaradi |
len, indeks, kesma |
||
in |
O(1) matematik tekshiruv |
Iste'mol qiladi |
| Holati | O'zgarmas (start, stop, step) |
Joriy pozitsiya |
Umumiy tamoyil: iterable (qayta aylanish mumkin — list, range, dict) va iterator (holatli, bir martalik) farqi. Iterator __iter__ da self qaytaradi.
6. Amaliy xulosa
- Funksiya argumentni ikki marta aylanishi kerak bo'lsa —
Iterableemas,SequenceyokiCollectionturini so'rang (13-qism) - Yoki boshida
list()ga aylantiring va buni hujjatlashtiring - Qayta o'qiladigan dangasa obyekt kerak —
__iter__da har safar yangi generator qaytaruvchi sinf yozing - Dangasa quvur xatolari kech chiqishini hisobga oling — chegaralarda tekshiring
Nimani mustahkamlaydi: 2.1–2.8-bo'limlar.
Xulosa
Bu darsda itertools ning asosiy vositalari va dangasa quvurlar bilan ishlashni o'rgandik.
Eng muhim uch fikr:
Dangasalik — kuch va tuzoq.
itertoolsnatijalari hech narsani oldindan hisoblamaydi: million qatorli jurnal quvuri bir megabaytdan kam xotirada ishladi, ro'yxat usuli esa o'nlab megabayt oldi. Lekin iteratorlar bir martalik: ikkinchi aylanish jim bo'sh natija beradi,inesa elementlarni iste'mol qiladi. Cheksizcount,cycle,repeat— doimisliceyokizipbilan chegaralanadi.Kesish, birlashtirish va paketlash.
isliceistalgan iteratorni kesadi (manfiy indekssiz),chain.from_iterabletekislaydi,pairwiseqo'shni juftliklarni,batchedpaketlarni beradi.zipuzunliklar farqini jim yashiradi —strict=Trueuni xatoga aylantiradi.accumulatekumulyativ yig'indi, rekordlar va prefiks yig'indilar uchun;takewhileesa shartga mos kelmagan birinchi elementni yutib yuboradi.groupby— faqat ketma-ket kelganlar. U SQLGROUP BYemas: saralanmagan ma'lumotda bir kalit bir necha guruhga bo'linadi va lug'atga yig'ilganda oldingi qiymat jim almashtiriladi. Guruhlar keyingi guruhga o'tilgach bo'shaydi — ularni darhol o'qing. Tartiblangan oqimlar (vaqt bo'yicha jurnal, ketma-ketliklarni siqish) uchungroupby, tartibsiz ma'lumot uchundefaultdict(list).
Keyingi darsda itertools ning kombinatorika qismiga o'tamiz: product, permutations, combinations va variantlar sonining portlovchi o'sishi.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!