IlmHamroh
Python kursi/Malumot tuzilmalari15/18-dars38 daqiqa
Mundarija (21)

6.15-dars: Ro'yxat generatori (list comprehension)

6-QISM — MA'LUMOT TUZILMALARI · 15-dars


1. Kirish va motivatsiya

Ro'yxat generatori — Pythonning eng tanilgan sintaksisi:

python
# Oddiy sikl
kvadratlar = []
for x in range(10):
    kvadratlar.append(x ** 2)

# Generator
kvadratlar = [x ** 2 for x in range(10)]

Bir qator o'rniga to'rt qator. Va u tezroq ham.

Lekin generator tez chalkash bo'lib ketadi:

python
# Bu nima qiladi?
natija = [y for x in matritsa for y in x if y > 0]

# Bu-chi?
[[f(x, y) for y in range(3)] for x in range(3)]

# Bu?
[x if x > 0 else 0 for x in sonlar]         # ✅
[x for x in sonlar if x > 0 else 0]         # ❌ SyntaxError

Va nozik tuzoqlar bor:

python
funksiyalar = [lambda: i for i in range(3)]
[f() for f in funksiyalar]                  # [2, 2, 2] ← nega?!

x = 10
[x for x in range(3)]
print(x)                                    # 10 — Python 3 da o'zgarmadi ✅

Bu darsda:

  • Sintaksis va bajarilish tartibi
  • if filtri va shartli ifoda — farqi
  • Ichma-ich generatorlar va ularning tartibi
  • Qamrov (scope) — Python 2 vs 3
  • Tezlik — nega generator tezroq
  • Qachon ishlatmaslik — o'qilish chegarasi

2. Nazariya — chuqur tushuntirish

2.1. Sintaksis

Asosiy shakl:

python
[IFODA for O'ZGARUVCHI in KETMA-KETLIK]
python
[x ** 2 for x in range(5)]              # [0, 1, 4, 9, 16]
[s.upper() for s in ["a", "b"]]         # ['A', 'B']
[len(s) for s in sozlar]

Filtr bilan:

python
[IFODA for O'ZGARUVCHI in KETMA-KETLIK if SHART]
python
[x for x in range(10) if x % 2 == 0]    # [0, 2, 4, 6, 8]
[s for s in sozlar if len(s) > 3]

Bajarilish tartibi — chapdan o'ngga, for dan boshlab:

python
[IFODA for x in KETMA-KETLIK if SHART]
   ↑        ↑                    ↑
   3        1                    2

Ya'ni:

  1. KETMA-KETLIK dan element olinadi
  2. SHART tekshiriladi
  3. Shart to'g'ri bo'lsa IFODA hisoblanadi

Ekvivalent sikl:

python
natija = []
for x in KETMA_KETLIK:
    if SHART:
        natija.append(IFODA)

if — filtr, if/else — ifoda:

python
[x for x in sonlar if x > 0]            # ✅ FILTR — elementlar tushib qoladi
[x if x > 0 else 0 for x in sonlar]     # ✅ IFODA — hamma element qoladi
[x for x in sonlar if x > 0 else 0]     # ❌ SyntaxError

Farq muhim:

python
sonlar = [-2, -1, 0, 1, 2]

[x for x in sonlar if x > 0]            # [1, 2]        — 2 element
[x if x > 0 else 0 for x in sonlar]     # [0, 0, 0, 1, 2] — 5 element

Ikkalasi birga:

python
[x * 2 if x > 0 else 0 for x in sonlar if x != 0]
#  ↑ ifoda (if/else)              ↑ filtr
# [0, 0, 2, 4]

Bu — chegara. Bundan murakkabroq bo'lsa oddiy sikl yozing.

2.2. Ichma-ich generatorlar

Ikki for — tekislash:

python
matritsa = [[1, 2], [3, 4], [5, 6]]

[y for x in matritsa for y in x]        # [1, 2, 3, 4, 5, 6]

Tartib — sikl bilan bir xil, chapdan o'ngga:

python
[y for x in matritsa for y in x]

# ekvivalenti:
natija = []
for x in matritsa:              # ← birinchi for
    for y in x:                 # ← ikkinchi for
        natija.append(y)

Bu — eng ko'p chalkashtiradigan joy. Ko'pchilik teskarisini kutadi.

Eslash usuli: for lar sikldagi kabi tartibda yoziladi, faqat IFODA oldinga chiqadi.

Ichma-ich ro'yxat qurish — ikkita []:

python
[[f(x, y) for y in range(3)] for x in range(2)]

# ekvivalenti:
natija = []
for x in range(2):
    qator = []
    for y in range(3):
        qator.append(f(x, y))
    natija.append(qator)

Solishtiring:

python
[y for x in m for y in x]               # TEKIS ro'yxat
[[y for y in x] for x in m]             # ICHMA-ICH ro'yxat (nusxa)

Ikkinchi for birinchisiga bog'liq bo'lishi mumkin:

python
[(i, j) for i in range(3) for j in range(i)]
# [(1,0), (2,0), (2,1)]

Har for dan keyin if:

python
[y for x in matritsa if len(x) > 1 for y in x if y > 2]
#                     ↑ birinchi filtr        ↑ ikkinchi filtr

Ekvivalenti:

python
for x in matritsa:
    if len(x) > 1:
        for y in x:
            if y > 2:
                natija.append(y)

2.3. Qamrov (scope)

Python 3 da generator o'zgaruvchisi tashqariga "sizmaydi":

python
x = 10
[x for x in range(3)]
print(x)                                # 10  ✅ o'zgarmadi

Python 2 da sizardi:

python
# Python 2
x = 10
[x for x in range(3)]
print x                                 # 2  ⚠️

Bu — Python 3 ning muhim tuzatishlaridan biri.

Qanday ishlaydi: generator o'zining yashirin funksiya qamrovi ichida bajariladi:

python
# [x**2 for x in r] taxminan shunga teng:
def _yashirin(iterator):
    natija = []
    for x in iterator:
        natija.append(x ** 2)
    return natija

_yashirin(iter(r))

Bir istisno — birinchi iterable tashqarida hisoblanadi:

python
[x for x in undefined_nom]              # ❌ NameError darhol
[undefined_nom for x in range(3)]       # ❌ NameError bajarilganda

Sinf tanasi ichida — nozik holat:

python
class A:
    qiymatlar = [1, 2, 3]
    ikkilangan = [x * 2 for x in qiymatlar]         # ✅ ishlaydi
    yigindi = [x + y for x in qiymatlar for y in qiymatlar]     # ❌ NameError!

Sabab: birinchi for ning iterable'i tashqi qamrovda hisoblanadi (qiymatlar — sinf atributi, ko'rinadi), lekin generator tanasi ichida sinf qamrovi ko'rinmaydi.

Yechim:

python
class A:
    qiymatlar = [1, 2, 3]
    yigindi = [x + y for x in qiymatlar for y in A.qiymatlar]   # ❌ A hali yo'q

To'g'ri yechim — generatorni sinfdan tashqarida yoki metod ichida yozish.

Kech bog'lanish (late binding) tuzog'i:

python
funksiyalar = [lambda: i for i in range(3)]
[f() for f in funksiyalar]              # [2, 2, 2]  ⚠️

Sabab: lambda i ni hisoblamaydi, faqat unga havola saqlaydi. Sikl tugaganda i == 2.

Yechim — sukut argument:

python
funksiyalar = [lambda i=i: i for i in range(3)]
[f() for f in funksiyalar]              # [0, 1, 2]  ✅

Yoki functools.partial:

python
from functools import partial
funksiyalar = [partial(lambda x: x, i) for i in range(3)]

Bu — 7-qismda batafsil ko'riladi.

2.4. Tezlik — nega generator tezroq

python
import timeit

timeit.timeit("[x*2 for x in range(1000)]", number=10000)       # ~0.35 s
timeit.timeit("""
natija = []
for x in range(1000):
    natija.append(x*2)
""", number=10000)                                              # ~0.62 s

~1.8x tezroq. Sabablar:

1. append metod qidiruvi yo'q:

Sikldagi har iteratsiyada:

  • natija nomini qidirish
  • .append atributini qidirish
  • Metod obyektini yaratish
  • Chaqirish

Generatorda — maxsus bytecode (LIST_APPEND), bularsiz.

2. Bytecode farqi:

python
import dis
dis.dis("[x*2 for x in r]")
#   ...
#   LIST_APPEND 2          ← C darajasida
python
dis.dis("""
n = []
for x in r: n.append(x*2)
""")
#   LOAD_NAME n
#   LOAD_METHOD append     ← har iteratsiyada
#   ...
#   CALL_METHOD 1
#   POP_TOP

3. Ro'yxat hajmi taxmin qilinadi:

Generator natija hajmini oldindan taxmin qiladi (kirish __len__ bo'lsa) va kamroq qayta ajratish qiladi.

Lekin funksiya chaqiruvi bo'lsa farq kamayadi:

python
[qimmat(x) for x in r]                  # farq ~5%
[x * 2 for x in r]                      # farq ~80%

Chunki qimmat(x) vaqti append narxidan katta.

map bilan solishtirish:

python
[f(x) for x in r]                       # generator
list(map(f, r))                         # map

map biroz tezroq (funksiya to'g'ridan-to'g'ri chaqiriladi), lekin faqat tayyor funksiya bilan:

python
list(map(str.upper, sozlar))            # ✅ tezroq
list(map(lambda x: x * 2, r))           # ⚠️ sekinroq (lambda qo'shimcha)
[x * 2 for x in r]                      # ✅ eng tez

2.5. Qachon ISHLATMASLIK

Generator — vosita, maqsad emas. U o'qilishni yaxshilaganda ishlatiladi.

1. Juda uzun yoki murakkab:

python
# ❌ O'qib bo'lmaydi
natija = [transform(x, y) for x in katta_royxat if shart1(x)
          for y in x.elementlar if shart2(y) and shart3(x, y)]

# ✅ Oddiy sikl
natija = []
for x in katta_royxat:
    if not shart1(x):
        continue
    for y in x.elementlar:
        if shart2(y) and shart3(x, y):
            natija.append(transform(x, y))

Amaliy qoida: ikkitadan ko'p for/if bo'lsa — sikl.

2. Yon ta'sir uchun:

python
[print(x) for x in r]                   # ❌ ro'yxat keraksiz yaratiladi
for x in r: print(x)                    # ✅

[d.update({x: 1}) for x in r]           # ❌
for x in r: d[x] = 1                    # ✅

Generator qiymat yaratish uchun. Yon ta'sir uchun — sikl.

3. Natija kerak bo'lmasa:

python
[f(x) for x in katta]                   # ⚠️ katta ro'yxat yaratiladi va tashlanadi
for x in katta: f(x)                    # ✅

any(f(x) for x in katta)                # ✅ generator ifodasi (17-dars)

4. Xotira muhim bo'lsa:

python
jami = sum([x ** 2 for x in range(10**7)])      # ⚠️ ~400 MB
jami = sum(x ** 2 for x in range(10**7))        # ✅ ~200 bayt

Generator ifodasi (qavssiz) — 17-dars.

5. Murakkab shart mantiqisi:

python
# ❌
[qayta_ishla(x) if turi(x) == "a" else boshqa(x) if turi(x) == "b" else sukut(x)
 for x in r]

# ✅ Funksiya ajrating
def qayta_ishla_bitta(x):
    match turi(x):
        case "a": return qayta_ishla(x)
        case "b": return boshqa(x)
        case _: return sukut(x)

[qayta_ishla_bitta(x) for x in r]

2.6. Muqobil shakllar

map va filter:

python
[f(x) for x in r]                       ≡  list(map(f, r))
[x for x in r if p(x)]                  ≡  list(filter(p, r))
[f(x) for x in r if p(x)]               ≡  list(map(f, filter(p, r)))

Qaysi birini:

python
list(map(str.upper, sozlar))            # ✅ tayyor funksiya — map o'qiladi
[s.upper() for s in sozlar]             # ✅ ham yaxshi
list(map(lambda s: s.upper(), sozlar))  # ⚠️ generator yaxshiroq

Qoida: lambda yozish kerak bo'lsa — generator.

itertools:

python
from itertools import chain, product, starmap

# Tekislash
[y for x in m for y in x]               ≡  list(chain.from_iterable(m))

# Dekart ko'paytmasi
[(i, j) for i in a for j in b]          ≡  list(product(a, b))

# Argumentlarni ochish
[f(*args) for args in juftliklar]       ≡  list(starmap(f, juftliklar))

numpy (katta sonli massivlar uchun):

python
[x ** 2 for x in katta_royxat]          # ~O(n) Python darajasida
np.array(katta) ** 2                    # ~50-100x tezroq

2.7. Boshqa generator turlari

Ro'yxat generatori — to'rtta shakldan biri:

python
[x for x in r]                          # list
{x for x in r}                          # set        (16-dars)
{k: v for k, v in r}                    # dict       (16-dars)
(x for x in r)                          # generator  (17-dars)

Tuple generatori yo'q:

python
(x for x in r)                          # generator, tuple EMAS!
tuple(x for x in r)                     # ✅ tuple

Sabab: () generator ifodasi uchun band. Bu — 17-darsda.


3. Tez ma'lumotnoma

Sintaksis

python
[IFODA for X in KETMA-KETLIK]
[IFODA for X in KETMA-KETLIK if SHART]
[IFODA if A else B for X in KETMA-KETLIK]       ⭐ ifoda
[IFODA for X in K1 for Y in K2]                 ichma-ich

Bajarilish: for → if → IFODA

if filtri vs if/else ifodasi

python
[x for x in s if x > 0]         FILTR — elementlar tushadi
[x if x > 0 else 0 for x in s]  IFODA — hamma qoladi
[x for x in s if x > 0 else 0]  ❌ SyntaxError

Ichma-ich tartib — sikldagi kabi

python
[y for x in m for y in x]       TEKIS
    ↑ 3     ↑ 1     ↑ 2

for x in m:          ← birinchi for
    for y in x:      ← ikkinchi for
        natija.append(y)

[[y for y in x] for x in m]     ICHMA-ICH

Qamrov

python
x = 10; [x for x in r]; print(x)    → 10  ✅ Python 3
⚠️ Sinf tanasida ikkinchi `for` sinf atributini KO'RMAYDI
⚠️ [lambda: i for i in range(3)] → hammasi 2 (kech bog'lanish)
   [lambda i=i: i for i in range(3)] ✅

Qachon ISHLATMASLIK

> 2 ta for/if                   → oddiy sikl
Yon ta'sir ([print(x) ...])     → oddiy sikl
Natija kerak emas               → sikl yoki generator ifodasi
Katta ma'lumot                  → (x for x in ...) 17-dars
Murakkab shart mantiqi          → funksiya ajrating

Muqobillar

python
list(map(f, r))                 tayyor funksiya bilan
list(filter(p, r))
chain.from_iterable(m)          tekislash
product(a, b)                   dekart ko'paytmasi
np.array(r) ** 2                sonli massiv — 50-100x

4. Batafsil misollar

Misol 1 — Sintaksis to'liq

python
"""Ro'yxat generatorining barcha shakllari."""

import dis

print("=== 1. Asosiy shakllar ===")

SONLAR = [-3, -1, 0, 2, 4, 7]
SOZLAR = ["olma", "anor", "shaftoli", "uzum", "behi"]

NAMUNALAR = [
    ("[x**2 for x in range(5)]",
     [x ** 2 for x in range(5)]),
    ("[s.upper() for s in SOZLAR]",
     [s.upper() for s in SOZLAR]),
    ("[len(s) for s in SOZLAR]",
     [len(s) for s in SOZLAR]),
    ("[x for x in SONLAR if x > 0]",
     [x for x in SONLAR if x > 0]),
    ("[s for s in SOZLAR if len(s) > 4]",
     [s for s in SOZLAR if len(s) > 4]),
    ("[x if x > 0 else 0 for x in SONLAR]",
     [x if x > 0 else 0 for x in SONLAR]),
    ("[abs(x) for x in SONLAR if x != 0]",
     [abs(x) for x in SONLAR if x != 0]),
]

for kod, natija in NAMUNALAR:
    print(f"  {kod:<40} → {natija}")


print("\n=== 2. ⚠️ if filtri vs if/else ifodasi ===")

print(f"  SONLAR = {SONLAR}\n")

filtr = [x for x in SONLAR if x > 0]
ifoda = [x if x > 0 else 0 for x in SONLAR]

print(f"  [x for x in s if x > 0]         → {filtr}")
print(f"                                     {len(filtr)} element (filtrlandi)")
print(f"\n  [x if x > 0 else 0 for x in s]  → {ifoda}")
print(f"                                     {len(ifoda)} element (hammasi)")

print(f"\n  ❌ [x for x in s if x > 0 else 0]:")
try:
    eval("[x for x in SONLAR if x > 0 else 0]")
except SyntaxError as x:
    print(f"     SyntaxError: {x.msg}")

print(f"\n  ✅ Ikkalasi birga:")
ikkalasi = [x * 10 if x > 0 else -1 for x in SONLAR if x != 0]
print(f"     [x*10 if x > 0 else -1 for x in s if x != 0]")
print(f"     → {ikkalasi}")
print(f"     ⚠️ Bu — o'qish chegarasi. Murakkabroq bo'lsa sikl yozing.")


print("\n=== 3. Bajarilish tartibi ===")

kuzatuv = []


def manba():
    for i in range(4):
        kuzatuv.append(f"manba({i})")
        yield i


def shart(x):
    kuzatuv.append(f"shart({x})")
    return x % 2 == 0


def ifoda(x):
    kuzatuv.append(f"ifoda({x})")
    return x * 10


natija = [ifoda(x) for x in manba() if shart(x)]

print(f"  [ifoda(x) for x in manba() if shart(x)]\n")
print(f"  Natija: {natija}\n")
print(f"  Chaqiruvlar tartibi:")
for i, q in enumerate(kuzatuv, 1):
    print(f"    {i:>2}. {q}")

print("""
  ⭐ Har element uchun:  manba → shart → (to'g'ri bo'lsa) ifoda
     Ya'ni: for → if → IFODA
""")


print("\n=== 4. Ichma-ich generatorlar ===")

MATRITSA = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]

print(f"  MATRITSA = {MATRITSA}\n")

tekis = [y for x in MATRITSA for y in x]
ichma_ich = [[y for y in x] for x in MATRITSA]
ikkilangan = [[y * 2 for y in x] for x in MATRITSA]

print(f"  [y for x in m for y in x]        → {tekis}")
print(f"                                     ⭐ TEKIS")
print(f"\n  [[y for y in x] for x in m]      → {ichma_ich}")
print(f"                                     ⭐ ICHMA-ICH (nusxa)")
print(f"\n  [[y*2 for y in x] for x in m]    → {ikkilangan}")

print(f"\n  ⚠️ Tartib — sikldagi kabi:")
print(f"""
    [y for x in m for y in x]
        ↑        ↑        ↑
      ifoda   1-for    2-for

    Ekvivalenti:
      for x in m:          ← BIRINCHI
          for y in x:      ← IKKINCHI
              natija.append(y)
""")

print(f"  Bog'liq ichma-ich:")
print(f"    [(i,j) for i in range(3) for j in range(i)]")
print(f"    → {[(i, j) for i in range(3) for j in range(i)]}")

print(f"\n  Uch daraja:")
uch = [x for a in [[[1, 2]], [[3], [4, 5]]] for b in a for x in b]
print(f"    [[[1,2]], [[3],[4,5]]] → {uch}")

print(f"\n  Har for dan keyin if:")
natija = [y for x in MATRITSA if len(x) > 2 for y in x if y % 2 == 0]
print(f"    [y for x in m if len(x)>2 for y in x if y%2==0]")
print(f"    → {natija}")
print(f"    (uzunligi > 2 bo'lgan qatorlardan juft sonlar)")


print("\n=== 5. Matritsa amallari ===")

M = [[1, 2, 3], [4, 5, 6]]

print(f"  M = {M}\n")

AMALLAR = [
    ("Transponirlash",      [[M[i][j] for i in range(len(M))] for j in range(len(M[0]))]),
    ("zip bilan (⭐)",       [list(q) for q in zip(*M)]),
    ("Har elementga *2",    [[x * 2 for x in qator] for qator in M]),
    ("Qatorlar yig'indisi", [sum(qator) for qator in M]),
    ("Ustunlar yig'indisi", [sum(q) for q in zip(*M)]),
    ("Tekislash",           [x for qator in M for x in qator]),
    ("Diagonal",            [M[i][i] for i in range(min(len(M), len(M[0])))]),
]

for nom, natija in AMALLAR:
    print(f"  {nom:<24} {natija}")

print(f"\n  Birlik matritsa:")
n = 4
birlik = [[1 if i == j else 0 for j in range(n)] for i in range(n)]
for qator in birlik:
    print(f"    {qator}")

print(f"\n  Ko'paytirish jadvali:")
jadval = [[i * j for j in range(1, 6)] for i in range(1, 6)]
print(f"       " + "".join(f"{j:>5}" for j in range(1, 6)))
for i, qator in enumerate(jadval, 1):
    print(f"    {i:>2} " + "".join(f"{x:>5}" for x in qator))


print("\n=== 6. Bytecode ===")

print("  [x*2 for x in r]:")
dis.dis("[x*2 for x in r]")

print("\n  Oddiy sikl:")
dis.dis("""
natija = []
for x in r:
    natija.append(x*2)
""")

print("""
  ⭐ Generator: LIST_APPEND — maxsus bytecode
     Sikl: LOAD_METHOD append + CALL_METHOD — har iteratsiyada
""")

Natijaning muhim qismi:

text
=== 2. ⚠️ if filtri vs if/else ifodasi ===
  SONLAR = [-3, -1, 0, 2, 4, 7]

  [x for x in s if x > 0]         → [2, 4, 7]
                                     3 element (filtrlandi)

  [x if x > 0 else 0 for x in s]  → [0, 0, 0, 2, 4, 7]
                                     6 element (hammasi)

=== 3. Bajarilish tartibi ===
  Chaqiruvlar tartibi:
     1. manba(0)
     2. shart(0)
     3. ifoda(0)
     4. manba(1)
     5. shart(1)
     6. manba(2)
     7. shart(2)
     8. ifoda(2)

=== 4. Ichma-ich generatorlar ===
  [y for x in m for y in x]        → [1, 2, 3, 4, 5, 6, 7, 8, 9]
                                     ⭐ TEKIS
  [[y for y in x] for x in m]      → [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
                                     ⭐ ICHMA-ICH (nusxa)

Nima ko'rsatdi: 2.1, 2.2-bo'limlar.

Misol 2 — Qamrov va tuzoqlar

python
"""Generator qamrovi va kech bog'lanish."""

print("=== 1. O'zgaruvchi sizib chiqmaydi (Python 3) ===")

x = 10
natija = [x for x in range(3)]
print(f"  x = 10")
print(f"  [x for x in range(3)]  →  {natija}")
print(f"  print(x)               →  {x}   ✅ o'zgarmadi")

print("""
  ⚠️ Python 2 da x = 2 bo'lardi — generator o'zgaruvchisi sizardi.
     Bu — Python 3 ning muhim tuzatishlaridan biri.
""")

print("  Ichkarida yashirin funksiya qamrovi bor:")
print("""
    [x**2 for x in r]  taxminan:

    def _yashirin(it):
        natija = []
        for x in it:
            natija.append(x**2)
        return natija

    _yashirin(iter(r))
""")


print("\n=== 2. Birinchi iterable tashqarida ===")

print("  Farqni ko'rsatish:\n")

try:
    [x for x in aniqlanmagan_nom]
except NameError as e:
    print(f"    [x for x in aniqlanmagan]  →  NameError: {e}")

def sinov():
    try:
        return [aniqlanmagan_nom for x in range(3)]
    except NameError as e:
        return f"NameError: {e}"

print(f"    [aniqlanmagan for x in r]  →  {sinov()}")

print("""
  ⭐ BIRINCHI `for` ning iterable'i tashqi qamrovda hisoblanadi,
     qolgan hamma narsa — generator ichida.
""")


print("\n=== 3. ⚠️ Sinf tanasi ichida ===")

print("  ✅ Ishlaydigan:")


class A:
    qiymatlar = [1, 2, 3]
    ikkilangan = [x * 2 for x in qiymatlar]         # birinchi for


print(f"    class A:")
print(f"        qiymatlar = [1, 2, 3]")
print(f"        ikkilangan = [x*2 for x in qiymatlar]")
print(f"    A.ikkilangan = {A.ikkilangan}")

print("\n  ❌ Ishlamaydigan:")
try:
    class B:
        qiymatlar = [1, 2, 3]
        juftliklar = [(x, y) for x in qiymatlar for y in qiymatlar]
except NameError as e:
    print(f"    class B:")
    print(f"        qiymatlar = [1, 2, 3]")
    print(f"        juftliklar = [(x,y) for x in qiymatlar for y in qiymatlar]")
    print(f"    → NameError: {e}")

print("""
  Sabab:
    • Birinchi `for` iterable'i — SINF qamrovida (ko'rinadi)
    • Ikkinchi `for` — generator ichida (sinf qamrovi KO'RINMAYDI)

  ⭐ Sinf tanasi — oddiy qamrov emas: u funksiyalar ichidan
     ko'rinmaydi. Generator esa yashirin funksiya.
""")

print("  ✅ Yechimlar:")


class C:
    qiymatlar = [1, 2, 3]

    @classmethod
    def juftliklar(cls):
        return [(x, y) for x in cls.qiymatlar for y in cls.qiymatlar]


print(f"    1. Metod ichida:  C.juftliklar() = {C.juftliklar()[:3]}...")

QIYMATLAR = [1, 2, 3]


class D:
    qiymatlar = QIYMATLAR
    juftliklar = [(x, y) for x in QIYMATLAR for y in QIYMATLAR]


print(f"    2. Modul darajasida: D.juftliklar[:3] = {D.juftliklar[:3]}...")


print("\n=== 4. ⚠️ Kech bog'lanish (late binding) ===")

funksiyalar = [lambda: i for i in range(3)]
natijalar = [f() for f in funksiyalar]

print(f"  funksiyalar = [lambda: i for i in range(3)]")
print(f"  [f() for f in funksiyalar]  →  {natijalar}   ⚠️ hammasi 2!")

print("""
  Sabab: lambda `i` ni HISOBLAMAYDI, faqat unga havola saqlaydi.
         Sikl tugaganda i == 2, va uchala lambda ham shuni ko'radi.
""")

print("  ✅ Yechimlar:\n")

f1 = [lambda i=i: i for i in range(3)]
print(f"    1. Sukut argument:")
print(f"       [lambda i=i: i for i in range(3)]  →  {[f() for f in f1]}")

from functools import partial
f2 = [partial(lambda x: x, i) for i in range(3)]
print(f"\n    2. functools.partial:")
print(f"       [partial(lambda x: x, i) ...]      →  {[f() for f in f2]}")


def yaratuvchi(i):
    return lambda: i


f3 = [yaratuvchi(i) for i in range(3)]
print(f"\n    3. Yaratuvchi funksiya:")
print(f"       [yaratuvchi(i) for i in range(3)]  →  {[f() for f in f3]}")

print("""
  ⚠️ Bu — generator emas, LAMBDA muammosi.
     Oddiy siklda ham xuddi shunday bo'ladi.
""")

f4 = []
for i in range(3):
    f4.append(lambda: i)
print(f"    Siklda ham: {[f() for f in f4]}   ⚠️ bir xil")


print("\n=== 5. Iteratsiya paytida o'zgartirish ===")

r = [1, 2, 3, 4, 5]
print(f"  r = {r}\n")

print(f"  ✅ Generator yangi ro'yxat yaratadi:")
r2 = [x for x in r if x % 2 == 0]
print(f"    r2 = [x for x in r if x%2==0]  →  r2={r2}, r={r}")

print(f"\n  ✅ Joyida almashtirish:")
r3 = [1, 2, 3, 4, 5]
r3[:] = [x for x in r3 if x % 2 == 0]
print(f"    r[:] = [x for x in r if ...]   →  {r3}")
print(f"    ⭐ Havolalar saqlanadi (6.2-dars)")

print(f"\n  ⚠️ Generator ichida asl ro'yxatni o'zgartirish:")
r4 = [1, 2, 3]
natija = [r4.append(x) or x for x in r4[:]]     # nusxa bo'yicha
print(f"    Nusxa bo'yicha iteratsiya  →  natija={natija}, r={r4}")


print("\n=== 6. Ichma-ich ro'yxat va nusxa ===")

ASL = [[1, 2], [3, 4]]

sayoz1 = [qator for qator in ASL]
sayoz2 = ASL.copy()
chuqur = [qator[:] for qator in ASL]

print(f"  ASL = {ASL}\n")
print(f"  {'Usul':<32} {'ASL[0] is nusxa[0]'}")
print("  " + "─" * 54)
print(f"  {'[qator for qator in ASL]':<32} {ASL[0] is sayoz1[0]}")
print(f"  {'ASL.copy()':<32} {ASL[0] is sayoz2[0]}")
print(f"  {'[qator[:] for qator in ASL]':<32} {ASL[0] is chuqur[0]}")

sayoz1[0].append(99)
print(f"\n  sayoz1[0].append(99)  →  ASL = {ASL}   ⚠️")
ASL[0].remove(99)

chuqur[0].append(99)
print(f"  chuqur[0].append(99)  →  ASL = {ASL}   ✅")

print("""
  ⭐ [qator for qator in m] — SAYOZ (ichki ro'yxatlar umumiy)
     [qator[:] for qator in m] — bir daraja chuqur
     copy.deepcopy(m) — to'liq (18-dars)
""")

Natijaning muhim qismi:

text
=== 3. ⚠️ Sinf tanasi ichida ===
  ✅ Ishlaydigan:
    A.ikkilangan = [2, 4, 6]

  ❌ Ishlamaydigan:
    → NameError: name 'qiymatlar' is not defined

=== 4. ⚠️ Kech bog'lanish (late binding) ===
  funksiyalar = [lambda: i for i in range(3)]
  [f() for f in funksiyalar]  →  [2, 2, 2]   ⚠️ hammasi 2!

  ✅ Yechimlar:
    1. Sukut argument:
       [lambda i=i: i for i in range(3)]  →  [0, 1, 2]

=== 6. Ichma-ich ro'yxat va nusxa ===
  Usul                             ASL[0] is nusxa[0]
  ──────────────────────────────────────────────────────
  [qator for qator in ASL]         True
  ASL.copy()                       True
  [qator[:] for qator in ASL]      False

Nima ko'rsatdi: 2.3-bo'lim.

Misol 3 — Tezlik va muqobillar

python
"""Generator vs sikl vs map vs numpy."""

import timeit
import sys
from itertools import chain, product, starmap

print("=== 1. Generator vs sikl ===")

SOZLASH = "r = list(range(1000))"

SINOVLAR = [
    ("[x*2 for x in r]",                "[x*2 for x in r]"),
    ("sikl + append",                   "n=[]\nfor x in r: n.append(x*2)"),
    ("sikl + append (lokal)",           "n=[]\nq=n.append\nfor x in r: q(x*2)"),
    ("list(map(...))",                  "list(map(lambda x: x*2, r))"),
    ("list(map(operator))",             "from operator import mul\n"
                                        "from functools import partial\n"
                                        "list(map(partial(mul, 2), r))"),
]

natijalar = []
for nom, kod in SINOVLAR:
    vaqt = timeit.timeit(kod, setup=SOZLASH, number=20_000)
    natijalar.append((nom, vaqt))

eng_tez = min(v for _, v in natijalar)
print(f"  1000 element × 20 000 marta:\n")
print(f"  {'Usul':<28} {'Vaqt':>9} {'Nisbat':>9}")
print("  " + "─" * 50)
for nom, vaqt in sorted(natijalar, key=lambda x: x[1]):
    print(f"  {nom:<28} {vaqt:>7.3f} s {vaqt / eng_tez:>8.2f}x")

print("""
  ⭐ Generator tezroq, chunki:
     • LIST_APPEND — maxsus bytecode
     • `.append` atributi har iteratsiyada qidirilmaydi
     • Natija hajmi oldindan taxmin qilinadi
""")


print("\n=== 2. Funksiya chaqiruvi bilan ===")


def qimmat(x):
    return sum(range(x % 50))


SOZLASH2 = """
r = list(range(500))
def qimmat(x): return sum(range(x % 50))
"""

SINOVLAR2 = [
    ("[qimmat(x) for x in r]",  "[qimmat(x) for x in r]"),
    ("sikl + append",           "n=[]\nfor x in r: n.append(qimmat(x))"),
    ("list(map(qimmat, r))",    "list(map(qimmat, r))"),
]

natijalar = []
for nom, kod in SINOVLAR2:
    vaqt = timeit.timeit(kod, setup=SOZLASH2, number=2_000)
    natijalar.append((nom, vaqt))

eng_tez = min(v for _, v in natijalar)
print(f"  Qimmat funksiya bilan:\n")
print(f"  {'Usul':<28} {'Vaqt':>9} {'Nisbat':>9}")
print("  " + "─" * 50)
for nom, vaqt in sorted(natijalar, key=lambda x: x[1]):
    print(f"  {nom:<28} {vaqt:>7.3f} s {vaqt / eng_tez:>8.2f}x")

print("""
  ⭐ Funksiya qimmat bo'lsa, farq YO'QOLADI —
     `append` narxi umumiy vaqtning kichik qismiga aylanadi.
""")


print("\n=== 3. map qachon yaxshiroq ===")

SOZLASH3 = "sozlar = ['salom', 'dunyo', 'python'] * 300"

SINOVLAR3 = [
    ("[s.upper() for s in sozlar]",     "[s.upper() for s in sozlar]"),
    ("list(map(str.upper, sozlar))",    "list(map(str.upper, sozlar))"),
    ("list(map(lambda s: s.upper(), ...))",
     "list(map(lambda s: s.upper(), sozlar))"),
]

natijalar = []
for nom, kod in SINOVLAR3:
    vaqt = timeit.timeit(kod, setup=SOZLASH3, number=20_000)
    natijalar.append((nom, vaqt))

eng_tez = min(v for _, v in natijalar)
print(f"  {'Usul':<40} {'Vaqt':>9} {'Nisbat':>9}")
print("  " + "─" * 62)
for nom, vaqt in sorted(natijalar, key=lambda x: x[1]):
    print(f"  {nom:<40} {vaqt:>7.3f} s {vaqt / eng_tez:>8.2f}x")

print("""
  ⭐ Qoida:
     • Tayyor funksiya (str.upper, int, len) → map biroz tezroq
     • lambda yozish kerak                    → generator
     • O'qilish muhim                         → generator
""")


print("\n=== 4. itertools muqobillari ===")

M = [[1, 2], [3, 4], [5, 6]]
A, B = [1, 2, 3], ["a", "b"]
JUFTLIKLAR = [(1, 2), (3, 4)]


def qoshish(x, y):
    return x + y


MUQOBILLAR = [
    ("Tekislash",
     [y for x in M for y in x],
     list(chain.from_iterable(M))),
    ("Dekart ko'paytmasi",
     [(i, j) for i in A for j in B],
     list(product(A, B))),
    ("Argumentlarni ochish",
     [qoshish(*args) for args in JUFTLIKLAR],
     list(starmap(qoshish, JUFTLIKLAR))),
]

print(f"  {'Vazifa':<24} {'Generator':<26} {'itertools'}")
print("  " + "─" * 68)
for nom, gen, it in MUQOBILLAR:
    belgi = "✅" if gen == it else "❌"
    print(f"  {nom:<24} {str(gen)[:24]:<26} {belgi} {str(it)[:20]}")

print(f"\n  Tezlik (tekislash, 1000 qator):")
SOZLASH4 = "m = [[i, i+1] for i in range(1000)]"
for nom, kod in [("[y for x in m for y in x]", "[y for x in m for y in x]"),
                 ("chain.from_iterable(m)",
                  "from itertools import chain\nlist(chain.from_iterable(m))")]:
    vaqt = timeit.timeit(kod, setup=SOZLASH4, number=10_000)
    print(f"    {nom:<32} {vaqt:.3f} s")


print("\n=== 5. Xotira: ro'yxat vs generator ifodasi ===")

N = 1_000_000

royxat = [x ** 2 for x in range(N)]
gen = (x ** 2 for x in range(N))

print(f"  {N:,} element:\n")
print(f"    Ro'yxat generatori:  {sys.getsizeof(royxat):>12,} bayt")
print(f"    Generator ifodasi:   {sys.getsizeof(gen):>12,} bayt")
print(f"    Farq:                {sys.getsizeof(royxat) / sys.getsizeof(gen):>12,.0f}x")

print(f"\n  Natija bir xil:")
print(f"    sum([x**2 for x in range(1000)]) = {sum([x ** 2 for x in range(1000)]):,}")
print(f"    sum(x**2 for x in range(1000))   = {sum(x ** 2 for x in range(1000)):,}")

print(f"\n  Tezlik:")
for nom, kod in [("sum([...])", "sum([x**2 for x in range(10000)])"),
                 ("sum(...)",   "sum(x**2 for x in range(10000))")]:
    vaqt = timeit.timeit(kod, number=2_000)
    print(f"    {nom:<16} {vaqt:.3f} s")

print("""
  ⚠️ Generator ifodasi biroz SEKINROQ (har element uchun
     yield mexanizmi), lekin xotira 40 000x kam.

  ⭐ Katta ma'lumot → generator ifodasi (17-dars)
     Kichik ma'lumot + qayta ishlatish → ro'yxat
""")

del royxat


print("\n=== 6. numpy bilan ===")

try:
    import numpy as np

    N = 1_000_000
    r = list(range(N))
    a = np.arange(N)

    import time

    boshlandi = time.perf_counter()
    n1 = [x ** 2 for x in r]
    vaqt_gen = time.perf_counter() - boshlandi

    boshlandi = time.perf_counter()
    n2 = a ** 2
    vaqt_np = time.perf_counter() - boshlandi

    print(f"  {N:,} element kvadrati:\n")
    print(f"    [x**2 for x in r]:   {vaqt_gen * 1000:>8.1f} ms")
    print(f"    numpy a**2:          {vaqt_np * 1000:>8.1f} ms")
    print(f"    Farq:                {vaqt_gen / vaqt_np:>8.0f}x")

    print(f"\n    Xotira:")
    print(f"      list:  {sys.getsizeof(n1):>12,} bayt (+ obyektlar)")
    print(f"      numpy: {n2.nbytes:>12,} bayt")

    del n1, n2

    print("""
  ⭐ Bir turdagi sonli massivlar uchun numpy —
     vektorlashtirilgan amallar C darajasida bajariladi.
     24-qismda batafsil.
""")
except ImportError:
    print("  (numpy o'rnatilmagan — o'tkazib yuborildi)")

Natijaning muhim qismi:

text
=== 1. Generator vs sikl ===
  1000 element × 20 000 marta:

  Usul                              Vaqt    Nisbat
  ──────────────────────────────────────────────────
  [x*2 for x in r]                 0.842 s     1.00x
  sikl + append (lokal)            1.124 s     1.33x
  sikl + append                    1.512 s     1.80x
  list(map(...))                   1.284 s     1.52x

=== 2. Funksiya chaqiruvi bilan ===
  Qimmat funksiya bilan:

  Usul                              Vaqt    Nisbat
  ──────────────────────────────────────────────────
  list(map(qimmat, r))             1.812 s     1.00x
  [qimmat(x) for x in r]           1.884 s     1.04x
  sikl + append                    1.941 s     1.07x

=== 5. Xotira: ro'yxat vs generator ifodasi ===
  1,000,000 element:

    Ro'yxat generatori:      8,448,728 bayt
    Generator ifodasi:             208 bayt
    Farq:                       40,619x

Nima ko'rsatdi: 2.4, 2.6-bo'limlar.

Misol 4 — Amaliy: ma'lumot qayta ishlash

python
"""Generatorlar bilan real vazifalar va o'qilish chegarasi."""

import re
from collections import Counter

print("=== 1. Matn qayta ishlash ===")

MATN = """
Python — kuchli va oddiy dasturlash tili. Python o'rganish oson,
lekin uning imkoniyatlari juda keng! Dasturlash tili sifatida
Python veb, ma'lumot tahlili va sun'iy intellektda ishlatiladi?
"""

TOXTASH = {"va", "u", "bu", "uchun", "bilan", "lekin", "ham", "sifatida"}

qatorlar = [q.strip() for q in MATN.strip().splitlines()]
sozlar = [s.lower().strip(".,!?—") for q in qatorlar for s in q.split()]
mazmunli = [s for s in sozlar if s and s not in TOXTASH]
uzunlar = [s for s in mazmunli if len(s) > 6]

print(f"  Qatorlar:      {len(qatorlar)}")
print(f"  Jami so'zlar:  {len(sozlar)}")
print(f"  Mazmunli:      {len(mazmunli)}")
print(f"  Uzun (>6):     {len(uzunlar)}\n")

print(f"  Uzun so'zlar: {uzunlar}")

hisob = Counter(mazmunli)
print(f"\n  Eng ko'p uchraganlar:")
for soz, n in hisob.most_common(5):
    print(f"    {soz:<16} {'█' * n} {n}")

print(f"\n  Uzunlik bo'yicha guruhlash:")
uzunliklar = sorted({len(s) for s in mazmunli})
for n in uzunliklar[-4:]:
    guruh = sorted({s for s in mazmunli if len(s) == n})
    print(f"    {n:>2} harf: {', '.join(guruh)}")


print("\n\n=== 2. Ma'lumot filtrlash va o'zgartirish ===")

XODIMLAR = [
    {"ism": "Aziz", "yosh": 30, "bolim": "IT", "maosh": 7_000_000, "faol": True},
    {"ism": "Bobur", "yosh": 25, "bolim": "HR", "maosh": 5_000_000, "faol": True},
    {"ism": "Aziza", "yosh": 35, "bolim": "IT", "maosh": 8_500_000, "faol": False},
    {"ism": "Dilnoza", "yosh": 28, "bolim": "Moliya", "maosh": 6_000_000, "faol": True},
    {"ism": "Eldor", "yosh": 42, "bolim": "IT", "maosh": 9_000_000, "faol": True},
]

SOROVLAR = [
    ("Barcha ismlar",
     [x["ism"] for x in XODIMLAR]),
    ("Faol xodimlar",
     [x["ism"] for x in XODIMLAR if x["faol"]]),
    ("IT bo'limi",
     [x["ism"] for x in XODIMLAR if x["bolim"] == "IT"]),
    ("Maoshi 6M dan yuqori",
     [x["ism"] for x in XODIMLAR if x["maosh"] > 6_000_000]),
    ("Faol IT xodimlari",
     [x["ism"] for x in XODIMLAR if x["faol"] and x["bolim"] == "IT"]),
    ("Ism + maosh",
     [(x["ism"], x["maosh"]) for x in XODIMLAR if x["faol"]]),
    ("15% oshirilgan maosh",
     [{**x, "maosh": round(x["maosh"] * 1.15)} for x in XODIMLAR if x["bolim"] == "IT"]),
]

for nom, natija in SOROVLAR[:6]:
    print(f"  {nom:<26} {natija}")

print(f"\n  15% oshirilgan (IT):")
for x in SOROVLAR[6][1]:
    print(f"    {x['ism']:<10} {x['maosh']:>10,}")

print(f"\n  Statistika:")
maoshlar = [x["maosh"] for x in XODIMLAR if x["faol"]]
print(f"    Faol xodimlar: {len(maoshlar)}")
print(f"    O'rtacha maosh: {sum(maoshlar) // len(maoshlar):,}")
print(f"    Eng katta:      {max(maoshlar):,}")

bolimlar = {x["bolim"] for x in XODIMLAR}
print(f"\n  Bo'lim bo'yicha:")
for b in sorted(bolimlar):
    guruh = [x for x in XODIMLAR if x["bolim"] == b]
    jami = sum(x["maosh"] for x in guruh)
    print(f"    {b:<10} {len(guruh)} xodim, jami {jami:>12,}")


print("\n\n=== 3. ⚠️ O'qilish chegarasi ===")

print("  ❌ Juda murakkab (3 for + 2 if):\n")
print("""    natija = [transform(x, y, z)
              for x in manba if shart1(x)
              for y in x.bolalar if shart2(x, y)
              for z in y.bolalar if shart3(z)]
""")

print("  ✅ Oddiy sikl — o'qish oson, tuzatish oson:\n")
print("""    natija = []
    for x in manba:
        if not shart1(x):
            continue
        for y in x.bolalar:
            if not shart2(x, y):
                continue
            for z in y.bolalar:
                if shart3(z):
                    natija.append(transform(x, y, z))
""")

print("  ✅ Yoki funksiyalarga ajrating:\n")
print("""    def mos_bolalar(x):
        return [y for y in x.bolalar if shart2(x, y)]

    natija = [transform(x, y, z)
              for x in manba if shart1(x)
              for y in mos_bolalar(x)
              for z in y.bolalar if shart3(z)]
""")

print("""  ⭐ Amaliy qoida:
     • 1 ta for + 1 ta if     → generator ✅
     • 2 ta for yoki 2 ta if  → generator, agar qisqa bo'lsa
     • 3 va undan ko'p        → sikl yoki funksiya ajrating
     • Bir qatorga sig'masa   → qayta o'ylang
""")


print("\n=== 4. ❌ Yon ta'sir uchun ishlatmang ===")

print("  ❌ Noto'g'ri:")
print("""    [print(x) for x in r]           # keraksiz ro'yxat
    [d.update({x: 1}) for x in r]   # None lar ro'yxati
    [f.write(q) for q in qatorlar]  # yozuv soni ro'yxati
""")

r = [1, 2, 3]
natija = [print(f"    {x}", end="") for x in r]
print(f"\n    Yaratilgan ro'yxat: {natija}   ⚠️ keraksiz")

print("\n  ✅ To'g'ri:")
print("""    for x in r: print(x)
    for x in r: d[x] = 1
    f.writelines(qatorlar)
""")

print("""
  ⭐ Generator — QIYMAT yaratish uchun.
     Yon ta'sir uchun — sikl.
""")


print("\n=== 5. Amaliy: log tahlili ===")

LOGLAR = [
    '192.168.1.1 - [08/Sep/2026:10:00:01] "GET / HTTP/1.1" 200 1234',
    '192.168.1.2 - [08/Sep/2026:10:00:05] "POST /api HTTP/1.1" 201 567',
    'notogri qator',
    '192.168.1.1 - [08/Sep/2026:10:00:12] "GET /admin HTTP/1.1" 403 89',
    '192.168.1.3 - [08/Sep/2026:10:00:15] "GET /api HTTP/1.1" 500 234',
    '192.168.1.1 - [08/Sep/2026:10:00:20] "GET /static/a.js HTTP/1.1" 304 0',
]

NAQSH = re.compile(
    r'(?P<ip>[\d.]+) - \[(?P<vaqt>[^\]]+)\] '
    r'"(?P<usul>\w+) (?P<yol>\S+) [^"]*" (?P<kod>\d+) (?P<hajm>\d+)'
)

# Bir bosqichda: parse + filtrlash
moslar = [m.groupdict() for q in LOGLAR if (m := NAQSH.match(q))]

print(f"  {len(LOGLAR)} qator → {len(moslar)} to'g'ri\n")

print(f"  ⭐ Walrus operatori (:=) bilan bir bosqichda:")
print(f"     [m.groupdict() for q in LOGLAR if (m := NAQSH.match(q))]")
print(f"     ← parse bir marta bajariladi\n")

print(f"  ❌ Walrus siz — ikki marta parse:")
print(f"     [NAQSH.match(q).groupdict() for q in LOGLAR if NAQSH.match(q)]\n")

xatolar = [m for m in moslar if int(m["kod"]) >= 400]
noyob_ip = sorted({m["ip"] for m in moslar})
yollar = Counter(m["yol"] for m in moslar)
trafik = sum(int(m["hajm"]) for m in moslar)

print(f"  Statistika:")
print(f"    To'g'ri qatorlar: {len(moslar)}")
print(f"    Xatolar (4xx/5xx): {len(xatolar)}")
print(f"    Noyob IP:         {len(noyob_ip)}  {noyob_ip}")
print(f"    Jami trafik:      {trafik:,} bayt")

print(f"\n  Xato so'rovlar:")
for m in xatolar:
    print(f"    {m['kod']} {m['usul']:<5} {m['yol']:<16} {m['ip']}")

print(f"\n  Eng ko'p so'ralgan yo'llar:")
for yol, n in yollar.most_common(3):
    print(f"    {yol:<18} {'█' * n} {n}")

print(f"\n  IP bo'yicha:")
for ip in noyob_ip:
    ip_soraovlar = [m for m in moslar if m["ip"] == ip]
    ip_yollar = sorted({m["yol"] for m in ip_soraovlar})
    print(f"    {ip:<16} {len(ip_soraovlar)} so'rov: {', '.join(ip_yollar)}")


print("\n\n=== 6. To'rt generator turi ===")

MALUMOT = ["olma", "anor", "olma", "behi", "anor", "olma"]

print(f"  Ma'lumot: {MALUMOT}\n")

TURLARI = [
    ("[x.upper() for x in m]",      [x.upper() for x in MALUMOT]),
    ("{x.upper() for x in m}",      {x.upper() for x in MALUMOT}),
    ("{x: len(x) for x in m}",      {x: len(x) for x in MALUMOT}),
    ("(x.upper() for x in m)",      (x.upper() for x in MALUMOT)),
    ("tuple(x for x in m)",         tuple(x for x in MALUMOT)),
]

for kod, natija in TURLARI:
    tur = type(natija).__name__
    korinish = str(natija) if tur != "generator" else "<generator obyekti>"
    print(f"  {kod:<28} {tur:<10} {korinish[:36]}")

print("""
  ⚠️ (x for x in m) — GENERATOR, tuple emas!
     tuple(x for x in m) — tuple

  16-dars: set va dict generatorlari
  17-dars: generator ifodalari
""")

Natijaning muhim qismi:

text
=== 2. Ma'lumot filtrlash va o'zgartirish ===
  Barcha ismlar              ['Aziz', 'Bobur', 'Aziza', 'Dilnoza', 'Eldor']
  Faol xodimlar              ['Aziz', 'Bobur', 'Dilnoza', 'Eldor']
  IT bo'limi                 ['Aziz', 'Aziza', 'Eldor']
  Faol IT xodimlari          ['Aziz', 'Eldor']

=== 5. Amaliy: log tahlili ===
  6 qator → 5 to'g'ri

  Statistika:
    To'g'ri qatorlar: 5
    Xatolar (4xx/5xx): 2
    Noyob IP:         3  ['192.168.1.1', '192.168.1.2', '192.168.1.3']
    Jami trafik:      2,124 bayt

=== 6. To'rt generator turi ===
  [x.upper() for x in m]       list       ['OLMA', 'ANOR', 'OLMA', 'BEHI', ...
  {x.upper() for x in m}       set        {'BEHI', 'OLMA', 'ANOR'}
  {x: len(x) for x in m}       dict       {'olma': 4, 'anor': 4, 'behi': 4}
  (x.upper() for x in m)       generator  <generator obyekti>

Nima ko'rsatdi: 2.1, 2.5, 2.7-bo'limlar.


5. To'g'ri va noto'g'ri tushunishlar

Noto'g'ri fikr To'g'risi
"[x for x in s if x > 0 else 0] ishlaydi" SyntaxError. if/else oldinda
"Ichma-ich for lar o'ngdan chapga" Chapdan o'ngga, sikldagi kabi
"Generator o'zgaruvchisi tashqariga sizadi" Python 3 da yo'q
"Generator har doim tezroq" Funksiya chaqiruvi bo'lsa farq yo'q
"map har doim tezroq" Faqat tayyor funksiya bilan
"(x for x in r) — tuple generatori" Generator ifodasi
"Yon ta'sir uchun ham ishlatsa bo'ladi" Ishlaydi, lekin noto'g'ri uslub
"Sinf tanasida ikki for ishlaydi" NameError
"[qator for qator in m] — chuqur nusxa" Sayoz — ichki ro'yxatlar umumiy

6. Keng tarqalgan xatolar va yechimlari

1. if/else joyi

python
[x for x in s if x > 0 else 0]          # ❌ SyntaxError
[x if x > 0 else 0 for x in s]          # ✅

2. Ichma-ich tartib

python
[y for y in x for x in m]               # ❌ NameError (x hali yo'q)
[y for x in m for y in x]               # ✅

3. Yon ta'sir

python
[print(x) for x in r]                   # ❌ keraksiz ro'yxat
for x in r: print(x)                    # ✅

4. Katta ma'lumot

python
sum([x**2 for x in range(10**7)])       # ⚠️ ~400 MB
sum(x**2 for x in range(10**7))         # ✅ ~200 bayt

5. Kech bog'lanish

python
[lambda: i for i in range(3)]           # ⚠️ hammasi 2
[lambda i=i: i for i in range(3)]       # ✅

6. Ikki marta hisoblash

python
[f(x) for x in r if f(x) > 0]           # ⚠️ f ikki marta
[y for x in r if (y := f(x)) > 0]       # ✅ walrus (3.8+)

7. Sayoz nusxa

python
nusxa = [qator for qator in m]          # ⚠️ ichki ro'yxatlar umumiy
nusxa = [qator[:] for qator in m]       # ✅ bir daraja
nusxa = copy.deepcopy(m)                # ✅ to'liq

8. Juda murakkab

python
[f(x,y,z) for x in a if p(x) for y in x if q(y) for z in y]     # ❌
# → oddiy sikl yoki funksiyalarga ajrating

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 6.16-dars: set va dict generatorlari
  • 6.17-dars: generator ifodalari — xotira tejash
  • 5.6, 5.7-darslar (o'tilgan): for, range, iteratsiya
  • 7-qism: lambda, map, filter, functools
  • 10, 15-qismlar: funksional dasturlash, itertools
  • 6.14-dars (o'tilgan): ichma-ich tuzilmalar bilan
  • 24-qism: numpy — vektorlashtirilgan amallar

8. Eng yaxshi amaliyotlar

  1. Bir for + bir if — ideal. Ikkitadan ko'p bo'lsa sikl haqida o'ylang.

  2. if/else — ifoda, if — filtr. Joylarini chalkashtirmang.

  3. Yon ta'sir uchun sikl. Generator qiymat yaratadi.

  4. Katta ma'lumot uchun generator ifodasi. sum(x for ...), [] siz.

  5. Ichma-ich for — sikldagi tartibda. Chapdan o'ngga.

  6. Tayyor funksiya bilan map ni ko'rib chiqing. lambda kerak bo'lsa — generator.

  7. Walrus bilan takroriy hisoblashdan qoching. if (y := f(x)).

  8. O'qib bo'lmasa — qayta yozing. Qisqalik o'qilishdan muhim emas.


9. Amaliy topshiriq

Vazifa 1: Natijani bashorat qiling

python
1.  print([x*2 for x in range(4)])
2.  print([x for x in range(6) if x % 2])
3.  print([x if x % 2 else 0 for x in range(6)])
4.  print([y for x in [[1,2],[3]] for y in x])
5.  print([[y for y in x] for x in [[1,2],[3]]])
6.  print([(i,j) for i in range(3) for j in range(i)])
7.  x = 5; [x for x in range(3)]; print(x)
8.  print([f() for f in [lambda: i for i in range(3)]])
9.  print([f() for f in [lambda i=i: i for i in range(3)]])
10. print(type((x for x in range(3))))
11. print([len(s) for s in "ab cd".split()])
12. print(len([print(x) for x in range(2)]))
Javoblar
  1. [0, 2, 4, 6]
  2. [1, 3, 5] — filtr
  3. [0, 1, 0, 3, 0, 5] — ifoda
  4. [1, 2, 3] — tekis
  5. [[1, 2], [3]] — ichma-ich
  6. [(1, 0), (2, 0), (2, 1)]
  7. 5 — sizmaydi
  8. [2, 2, 2] — kech bog'lanish
  9. [0, 1, 2] — sukut argument
  10. <class 'generator'> — tuple emas!
  11. [2, 2]
  12. 0 va 1 chiqadi, keyin 2 — None lar ro'yxati uzunligi

Vazifa 2: Xatolarni tuzating

python
1.  [x for x in s if x > 0 else 0]
2.  [y for y in x for x in m]
3.  [print(x) for x in r]
4.  jami = sum([x**2 for x in range(10**7)])
5.  [f(x) for x in r if f(x) > 0]
6.  nusxa = [q for q in matritsa]     # mustaqil bo'lishi kerak
7.  fs = [lambda: i for i in range(3)]
8.  class A:
        q = [1,2]
        j = [(x,y) for x in q for y in q]
Javoblar
python
1.  [x if x > 0 else 0 for x in s]
2.  [y for x in m for y in x]
3.  for x in r: print(x)
4.  jami = sum(x**2 for x in range(10**7))
5.  [y for x in r if (y := f(x)) > 0]
6.  nusxa = [q[:] for q in matritsa]
7.  fs = [lambda i=i: i for i in range(3)]
8.  Q = [1,2]  # modul darajasida
    class A:
        q = Q
        j = [(x,y) for x in Q for y in Q]

Vazifa 3: Generatorga aylantiring

Har bir siklni generatorga aylantiring (yoki "sikl yaxshiroq" deb izohlang):

python
1.  n=[]
    for x in r: n.append(x*2)

2.  n=[]
    for x in r:
        if x > 0: n.append(x)

3.  n=[]
    for q in matritsa:
        for x in q: n.append(x)

4.  n=[]
    for x in r:
        if x > 0: n.append(x)
        else: n.append(0)

5.  jami = 0
    for x in r: jami += x

6.  for x in r: print(x)

7.  n = {}
    for x in r: n[x] = len(x)

8.  n=[]
    for x in a:
        for y in b:
            if p(x,y): n.append(f(x,y))

Vazifa 4: Matritsa kutubxonasi

Generatorlar bilan yozing:

  1. transponir(m) — transponirlash
  2. kopaytir(a, b) — matritsalar ko'paytmasi
  3. birlik(n) — birlik matritsa
  4. qoshish(a, b) — element bo'yicha
  5. minor(m, i, j) — i-qator, j-ustunsiz
  6. aylantir(m) — 90° burish
  7. Har biri uchun sikl versiyasi bilan tezlikni solishtiring

Vazifa 5: Ma'lumot quvuri

CSV kabi ma'lumot bilan:

  1. Parse (walrus bilan bir bosqichda)
  2. Filtrlash (bir necha shart)
  3. Turlarni aylantirish
  4. Guruhlash va agregatsiya
  5. Saralash va cheklash
  6. Har qadamni generator bilan, keyin sikl bilan yozing
  7. O'qilish va tezlikni solishtiring

Vazifa 6: O'qilish tahlilchisi

Dastur yozing:

  1. Kod faylidan generatorlarni topsin (ast moduli bilan)
  2. Har biri uchun murakkablikni baholasin (for va if soni)
  3. Uzunligini o'lchasin
  4. Chegaradan oshganlarni belgilasin
  5. Sikl versiyasini taklif qilsin

Vazifa 7: O'ylash

Nega Python [x for x in r] ni oddiy sikldan tezroq qildi, lekin (x for x in r) (generator ifodasi) sekinroq?

Javob

Ular turli narsalarni optimallashtiradi.

Ro'yxat generatori — bajarilish tezligi:

CPython [x for x in r] uchun maxsus bytecode beradi:

LIST_APPEND n

Bu — bitta instruksiya. Oddiy sikl esa:

LOAD_NAME     natija
LOAD_METHOD   append          ← lug'atdan qidirish
LOAD_FAST     x
CALL_METHOD   1               ← funksiya chaqiruvi
POP_TOP                       ← None ni tashlash

Beshta instruksiya, ikkitasi qimmat (atribut qidiruvi va metod chaqiruvi).

Qo'shimcha: generator ro'yxat hajmini oldindan taxmin qiladi (kirish __len__ bo'lsa) — kamroq qayta ajratish.

Natija: ~1.8x tezroq.

Generator ifodasi — xotira, tezlik emas:

(x for x in r) generator obyekti yaratadi. Har next() chaqiruvida:

  1. Generator freym'i tiklanadi (holat: qayerda to'xtagan edi)
  2. Bir qadam bajariladi
  3. yield da to'xtaydi, freym saqlanadi
  4. Qiymat qaytariladi

Bu — freym almashish (frame switching). U arzon emas: ~50-100 ns har element uchun.

Ro'yxat generatorida esa hamma narsa bir freymda bajariladi.

Natija:

python
sum([x for x in range(10**6)])          # ~45 ms
sum(x for x in range(10**6))            # ~65 ms   ← ~45% sekinroq

Lekin xotira:

python
sys.getsizeof([x for x in range(10**6)])    # 8,448,728 bayt
sys.getsizeof(x for x in range(10**6))      # 208 bayt

40 000x kam.

Savdo:

Ro'yxat generatori Generator ifodasi
Tezlik Tezroq ~40% sekinroq
Xotira O(n) O(1)
Qayta o'tish Bir marta
Indeks/len
Dangasa Kerak bo'lganda

Qachon qaysi biri:

python
# Kichik ma'lumot, qayta ishlatiladi → ro'yxat
kalitlar = [k for k in d if shart(k)]
for k in kalitlar: ...
for k in kalitlar: ...           # ikkinchi marta

# Katta ma'lumot, bir marta → generator
jami = sum(x**2 for x in katta_fayl_qatorlari())

# Erta to'xtash → generator ⭐
birinchi = next(x for x in katta if shart(x))
any(shart(x) for x in katta)     # birinchi True da to'xtaydi

Oxirgi holat ayniqsa muhim:

python
any([qimmat(x) for x in katta])          # ⚠️ HAMMASI hisoblanadi
any(qimmat(x) for x in katta)            # ✅ birinchi True da to'xtaydi

Bu yerda generator tezroq ham bo'lishi mumkin — chunki u kamroq ish bajaradi.

Xulosa: "tezroq" savolining javobi kontekstga bog'liq. Ro'yxat generatori bir xil ishni tezroq bajaradi. Generator ifodasi kamroq ish bajarishga imkon beradi (dangasa hisoblash) va xotira tejaydi.

Amaliy qoida: natija to'liq kerak bo'lsa — ro'yxat, oqim sifatida ishlatilsa — generator.

Nimani mustahkamlaydi: 2.4, 2.5, 2.7-bo'limlar.


Xulosa

Bu darsda ro'yxat generatorlarini o'rgandik.

Eng muhim uch fikr:

  1. if filtri va if/else ifodasi — turli joylarda. [x for x in s if x > 0] elementlarni tushiradi, [x if x > 0 else 0 for x in s] hammasini saqlaydi. Ikkinchisi for dan oldin yoziladi.

  2. Ichma-ich for lar sikldagi tartibda. [y for x in m for y in x] — avval x, keyin y. Bu — eng ko'p chalkashtiradigan joy. Ikkita [] esa ichma-ich ro'yxat quradi.

  3. Generator — o'qilish uchun, tezlik uchun emas. U ~1.8x tezroq, lekin bu ikkinchi darajali. Ikkitadan ko'p for/if bo'lsa yoki yon ta'sir kerak bo'lsa — oddiy sikl yozing.

Keyingi darsda set va dict generatorlarini ko'ramiz: bir xil sintaksis, lekin noyoblik va kalit-qiymat semantikasi bilan.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
6.15-dars: Ro'yxat generatori (list comprehension) — IlmHamroh