IlmHamroh
Python kursi/Boshqaruv oqimi7/12-dars26 daqiqa
Mundarija (23)

5.7-dars: range() chuqur

5-QISM — BOSHQARUV OQIMI · 7-dars


1. Kirish va motivatsiya

range() — for sikli bilan eng ko'p ishlatiladigan funksiya:

python
for i in range(5):
    print(i)                # 0 1 2 3 4

Sodda ko'rinadi. Lekin range — oddiy funksiya emas, u alohida tur:

python
print(type(range(5)))       # <class 'range'>
print(range(5))             # range(0, 5)  ← ro'yxat emas!
print(list(range(5)))       # [0, 1, 2, 3, 4]

Va u hayratlanarli darajada samarali:

python
import sys

print(sys.getsizeof(range(1_000_000)))          # 48 bayt
print(sys.getsizeof(list(range(1_000_000))))    # 8,000,056 bayt

Bir million element — 48 bayt. Qanday?

Bu darsda:

  • range — nima uchun ro'yxat emas
  • Uch shakli va stop kirmasligi
  • Manfiy qadam va teskari yurish
  • range metodlari: in, len, index, kesim
  • Eng ko'p uchraydigan xatolar
  • Qachon range, qachon boshqa narsa

2. Nazariya — chuqur tushuntirish

2.1. Uch shakl

python
range(stop)                     # 0 dan stop gacha, qadam 1
range(start, stop)              # start dan stop gacha, qadam 1
range(start, stop, step)        # qadam bilan
python
print(list(range(5)))               # [0, 1, 2, 3, 4]
print(list(range(2, 5)))            # [2, 3, 4]
print(list(range(0, 10, 2)))        # [0, 2, 4, 6, 8]
print(list(range(10, 0, -1)))       # [10, 9, 8, ..., 1]

stop KIRMAYDI — kesimlar bilan bir xil qoida (4.2-dars):

python
print(list(range(5)))               # 0..4 — 5 YO'Q
print(len(range(5)))                # 5 — aynan 5 ta element

Nega shunday?

python
# 1. Uzunlik oddiy
print(len(range(a, b)) == b - a)    # True

# 2. Bo'lish va birlashtirish
print(list(range(0, 5)) + list(range(5, 10)) == list(range(10)))    # True

# 3. Indekslar bilan mos
royxat = [10, 20, 30]
for i in range(len(royxat)):        # 0, 1, 2 — aynan yaroqli indekslar
    print(royxat[i])

Agar stop kirsaganda range(len(royxat)) chegaradan chiqardi.

Bo'sh range:

python
print(list(range(0)))               # []
print(list(range(5, 5)))            # []
print(list(range(5, 0)))            # []  — musbat qadamda start > stop
print(list(range(0, 5, -1)))        # []  — manfiy qadamda start < stop

range xato bermaydi:

python
print(list(range(10, 0)))           # [] — bo'sh, xato emas
# range(0, 5, 0)                    # ❌ ValueError: arg 3 must not be zero

Faqat step=0 xato beradi.

2.2. range — ro'yxat emas

python
r = range(5)

print(type(r))                      # <class 'range'>
print(r)                            # range(0, 5)
print(list(r))                      # [0, 1, 2, 3, 4]

Xotira:

python
import sys

print(f"  range(10):        {sys.getsizeof(range(10)):>12,} bayt")
print(f"  range(1_000_000): {sys.getsizeof(range(1_000_000)):>12,} bayt")
print(f"  list(range(10)):  {sys.getsizeof(list(range(10))):>12,} bayt")
print(f"  list(1_000_000):  {sys.getsizeof(list(range(1_000_000))):>12,} bayt")
text
  range(10):                  48 bayt
  range(1_000_000):           48 bayt
  list(range(10)):           136 bayt
  list(1_000_000):     8,000,056 bayt

Nega? range faqat uch sonni saqlaydi: start, stop, step. Elementlar hisoblanadi:

text
i-element = start + i × step
python
r = range(10, 100, 5)
print(r.start, r.stop, r.step)      # 10 100 5
print(r[3])                         # 25 = 10 + 3*5
print(len(r))                       # 18

len formulasi:

python
def range_uzunlik(start, stop, step):
    if step > 0:
        return max(0, (stop - start + step - 1) // step)
    return max(0, (start - stop - step - 1) // (-step))


print(range_uzunlik(0, 10, 3))      # 4  — [0, 3, 6, 9]
print(len(range(0, 10, 3)))         # 4

Amaliy natija: range(10**18) — muammosiz:

python
r = range(10 ** 18)
print(len(r))                       # 1000000000000000000
print(r[999_999_999])               # 999999999
print(10 ** 15 in r)                # True — darhol

Lekin list(range(10**18)) — xotira tugaydi.

2.3. range metodlari

range — ketma-ketlik (sequence), shuning uchun:

python
r = range(0, 20, 3)                 # [0, 3, 6, 9, 12, 15, 18]

print(len(r))                       # 7
print(r[0], r[-1])                  # 0 18
print(r[2:5])                       # range(6, 15, 3)  ← range qaytadi!
print(list(r[2:5]))                 # [6, 9, 12]
print(9 in r)                       # True
print(10 in r)                      # False
print(r.index(9))                   # 3
print(r.count(9))                   # 1
print(list(reversed(r)))            # [18, 15, 12, 9, 6, 3, 0]

in — O(1)!

python
import time

r = range(100_000_000)
royxat = list(range(100_000))

boshlandi = time.perf_counter()
99_999_999 in r
vaqt_range = time.perf_counter() - boshlandi

boshlandi = time.perf_counter()
99_999 in royxat
vaqt_royxat = time.perf_counter() - boshlandi

print(f"  range da:   {vaqt_range * 1_000_000:>8.1f} µs  (100M element)")
print(f"  ro'yxatda:  {vaqt_royxat * 1_000_000:>8.1f} µs  (100K element)")

range matematik hisob qiladi:

python
def range_in(qiymat, r):
    if r.step > 0:
        if not (r.start <= qiymat < r.stop):
            return False
    else:
        if not (r.stop < qiymat <= r.start):
            return False
    return (qiymat - r.start) % r.step == 0

Lekin in faqat sonlar uchun O(1):

python
print("a" in range(5))              # False — O(n) qidiruv, lekin tez tugaydi

Kesim range qaytaradi:

python
r = range(0, 100, 5)
print(r[10:20])                     # range(50, 100, 5)
print(r[::2])                       # range(0, 100, 10)
print(r[::-1])                      # range(95, -5, -5)

Bu — xotira tejaydi.

Solishtirish:

python
print(range(5) == range(5))                     # True
print(range(0, 5) == range(0, 5, 1))            # True
print(range(0) == range(5, 5))                  # True — ikkalasi bo'sh
print(range(0, 5, 2) == range(0, 6, 2))         # True — bir xil elementlar!

range elementlari bo'yicha solishtiriladi, atributlari bo'yicha emas.

2.4. Manfiy qadam

python
print(list(range(10, 0, -1)))       # [10, 9, ..., 1]
print(list(range(10, -1, -1)))      # [10, 9, ..., 0]  ← 0 ni ham
print(list(range(0, -5, -1)))       # [0, -1, -2, -3, -4]

Klassik tuzoq — 0 kirmaydi:

python
print(list(range(5, 0, -1)))        # [5, 4, 3, 2, 1]  ← 0 YO'Q
print(list(range(5, -1, -1)))       # [5, 4, 3, 2, 1, 0]  ✅

stop kirmaydi qoidasi manfiy qadamda ham amal qiladi.

Ro'yxatni teskari bo'ylab yurish:

python
royxat = ["a", "b", "c", "d"]

# ❌ Chalkash
for i in range(len(royxat) - 1, -1, -1):
    print(royxat[i])

# ✅ reversed
for x in reversed(royxat):
    print(x)

# ✅ Indeks kerak bo'lsa
for i in reversed(range(len(royxat))):
    print(i, royxat[i])

# ✅ Yoki
for i, x in reversed(list(enumerate(royxat))):
    print(i, x)

Teskari yurish — element o'chirishda kerak (6-dars):

python
for i in range(len(royxat) - 1, -1, -1):
    if shart(royxat[i]):
        del royxat[i]               # ✅ indekslar buzilmaydi

2.5. Eng ko'p uchraydigan xatolar

1. range(len(x)) — noidiomatik:

python
for i in range(len(royxat)):        # ⚠️
    print(royxat[i])

for x in royxat:                    # ✅
    print(x)

for i, x in enumerate(royxat):      # ✅ indeks kerak bo'lsa
    print(i, x)

Ruff: C0200 (pylint), B007.

2. Off-by-one:

python
# 1 dan 10 gacha (10 ni ham)
for i in range(1, 10):              # ❌ 1..9
for i in range(1, 11):              # ✅ 1..10

3. range ni ro'yxat deb o'ylash:

python
r = range(5)
# r.append(5)                       # ❌ AttributeError
# r[0] = 10                         # ❌ TypeError

royxat = list(range(5))             # ✅

4. Kasr sonlar:

python
# range(0, 1, 0.1)                  # ❌ TypeError: must be integers

# ✅ Yechimlar
for i in range(10):
    x = i / 10

import numpy as np                  # ✅ (24-qism)
for x in np.arange(0, 1, 0.1):
    ...

from decimal import Decimal         # ✅ aniq
qadam = Decimal("0.1")
x = Decimal("0")
while x < 1:
    ...
    x += qadam

5. Katta range ni ro'yxatga aylantirish:

python
# royxat = list(range(10 ** 9))     # ❌ ~8 GB xotira
for i in range(10 ** 9):            # ✅ xotira ishlatmaydi
    ...

6. Siklda range ni qayta yaratish:

python
for i in range(len(royxat)):        # len har iteratsiyada emas — bir marta ✅
    ...

# Lekin:
for i in range(len(royxat)):
    for j in range(len(royxat)):    # ⚠️ ichki siklda har safar
        ...

n = len(royxat)                     # ✅
for i in range(n):
    for j in range(n):
        ...

Aslida range(len(x)) da len bir marta chaqiriladi — range yaratilganda. Lekin ichki siklda range obyekti har safar yaratiladi.

2.6. range va boshqa vositalar

itertools.count — cheksiz (15-qism):

python
from itertools import count

for i in count():                   # 0, 1, 2, ... cheksiz
    if i > 5:
        break

for i in count(10, 5):              # 10, 15, 20, ...
    ...

itertools.islice — cheksizdan kesim:

python
from itertools import count, islice

print(list(islice(count(0, 3), 5)))     # [0, 3, 6, 9, 12]

numpy.arange va linspace (24-qism):

python
import numpy as np

print(np.arange(0, 1, 0.25))        # [0.   0.25 0.5  0.75]
print(np.linspace(0, 1, 5))         # [0.   0.25 0.5  0.75 1.  ]
Vosita Kasr Cheksiz Xotira
range O(1)
count O(1)
np.arange O(n)
np.linspace O(n)

Kasr diapazon funksiyasi:

python
def frange(start: float, stop: float, step: float = 1.0):
    """Kasr sonli range."""
    n = int(round((stop - start) / step))
    for i in range(n):
        yield start + i * step


print(list(frange(0, 1, 0.25)))     # [0.0, 0.25, 0.5, 0.75]

Kasr xatolari to'planmasligi uchun start + i * step ishlatiladi, x += step emas (3.4-dars, 5.5-dars).

2.7. Amaliy naqshlar

1. N marta takrorlash:

python
for _ in range(3):
    print("Salom")

2. Indeks bo'ylab:

python
for i in range(len(royxat)):
    royxat[i] *= 2                  # elementni o'zgartirish

Bu — for x in royxat bilan qilib bo'lmaydi (o'zgaruvchi nusxa).

3. Bo'laklarga bo'lish:

python
def boklarga_bol(royxat, hajm):
    for i in range(0, len(royxat), hajm):
        yield royxat[i:i + hajm]


print(list(boklarga_bol([1,2,3,4,5,6,7], 3)))
# [[1, 2, 3], [4, 5, 6], [7]]

4. Juftliklar:

python
for i in range(len(royxat) - 1):
    print(royxat[i], royxat[i + 1])

# Yoki (Python 3.10+)
from itertools import pairwise
for a, b in pairwise(royxat):
    print(a, b)

5. Jadval (ichma-ich):

python
for i in range(1, 4):
    for j in range(1, 4):
        print(f"{i}×{j}={i*j}", end="  ")
    print()

6. Teskari yurish (o'chirish uchun):

python
for i in range(len(royxat) - 1, -1, -1):
    if royxat[i] is None:
        del royxat[i]

7. Qadam bilan:

python
for i in range(0, 100, 10):         # 0, 10, 20, ..., 90
    print(i)

8. Ikkilik qidiruv chegaralari:

python
chap, ong = 0, len(royxat) - 1
while chap <= ong:
    orta = (chap + ong) // 2
    ...

2.8. Tezlik

python
import time

N = 1_000_000

# range bilan
boshlandi = time.perf_counter()
jami = 0
for i in range(N):
    jami += i
vaqt_range = time.perf_counter() - boshlandi

# Ro'yxat bilan
royxat = list(range(N))
boshlandi = time.perf_counter()
jami = 0
for i in royxat:
    jami += i
vaqt_royxat = time.perf_counter() - boshlandi

# sum
boshlandi = time.perf_counter()
jami = sum(range(N))
vaqt_sum = time.perf_counter() - boshlandi

# Matematik formula
boshlandi = time.perf_counter()
jami = N * (N - 1) // 2
vaqt_formula = time.perf_counter() - boshlandi

print(f"  for + range:  {vaqt_range * 1000:>9.2f} ms")
print(f"  for + list:   {vaqt_royxat * 1000:>9.2f} ms")
print(f"  sum(range):   {vaqt_sum * 1000:>9.2f} ms")
print(f"  Formula:      {vaqt_formula * 1000:>9.6f} ms")

Xulosa: range va ro'yxat bo'ylab yurish deyarli bir xil tez, lekin range xotira ishlatmaydi.

Eng tez — matematik formula. Sikl kerak bo'lmasa, uni ishlatmang.

2.9. range va o'zgarmaslik

range — o'zgarmas (4.12-dars):

python
r = range(5)
# r[0] = 10                         # ❌ TypeError
# r.append(5)                       # ❌ AttributeError

Xeshlanadi:

python
print(hash(range(5)))               # ✅ ishlaydi
print({range(5): "a"})              # ✅ lug'at kaliti
print({range(5), range(3)})         # ✅ to'plam elementi

Qayta ishlatiladi (iterator emas — 6-dars):

python
r = range(3)
print(list(r))                      # [0, 1, 2]
print(list(r))                      # [0, 1, 2]  ✅ qayta ishlaydi

Bu — generatorlardan farqi:

python
g = (x for x in range(3))
print(list(g))                      # [0, 1, 2]
print(list(g))                      # []  ← bir martalik

3. Tez ma'lumotnoma

Uch shakl

python
range(stop)                 0 dan stop gacha (stop KIRMAYDI)
range(start, stop)
range(start, stop, step)

range(5)        → 0 1 2 3 4
range(2, 5)     → 2 3 4
range(0, 10, 2) → 0 2 4 6 8
range(5, 0, -1) → 5 4 3 2 1     ⚠️ 0 YO'Q
range(5, -1, -1)→ 5 4 3 2 1 0   ✅

Xususiyatlari

python
type(range(5))      → range (ro'yxat EMAS)
sys.getsizeof()     → 48 bayt (hajmdan qat'i nazar)
len(r)              O(1)
r[i]                O(1)
x in r              O(1) — sonlar uchun
r[a:b]              range qaytaradi
reversed(r)         range_iterator
Qayta ishlatiladi   ✅ (generator emas)
Xeshlanadi          ✅

Xatolar

python
range(0, 1, 0.1)            ❌ TypeError — faqat butun sonlar
list(range(10**9))          ❌ ~8 GB xotira
range(0, 5, 0)              ❌ ValueError
for i in range(len(x)):     ⚠️ enumerate ishlating
range(1, 10) → 1..9         ⚠️ off-by-one

Muqobillar

python
itertools.count()           cheksiz
itertools.islice()          cheksizdan kesim
np.arange(0, 1, 0.1)        kasr (24-qism)
np.linspace(0, 1, 5)        n ta nuqta

4. Batafsil misollar

Misol 1 — range ichkarisi

python
"""range nima uchun ro'yxat emas."""

import sys
import time

print("=== 1. Xotira ===")

hajmlar = [10, 1_000, 1_000_000, 10 ** 12]

print(f"  {'Hajm':>16} {'range':>12} {'list':>16}")
print("  " + "─" * 48)

for n in hajmlar:
    r = sys.getsizeof(range(n))
    if n <= 1_000_000:
        l = sys.getsizeof(list(range(n)))
        l_matn = f"{l:,}"
    else:
        l_matn = "(xotira yetmaydi)"
    print(f"  {n:>16,} {r:>12} {l_matn:>16}")

print("\n  range faqat 3 sonni saqlaydi: start, stop, step")


print("\n\n=== 2. Elementlar hisoblanadi ===")

r = range(10, 100, 7)
print(f"  r = range(10, 100, 7)")
print(f"    r.start = {r.start}, r.stop = {r.stop}, r.step = {r.step}")
print(f"    len(r)  = {len(r)}")
print(f"    list(r) = {list(r)}")

print(f"\n  i-element = start + i × step:")
for i in range(4):
    hisoblangan = r.start + i * r.step
    print(f"    r[{i}] = {r[i]:>3}   (10 + {i}×7 = {hisoblangan})")


print("\n\n=== 3. len formulasi ===")


def range_uzunlik(start, stop, step):
    if step > 0:
        return max(0, (stop - start + step - 1) // step)
    return max(0, (start - stop - step - 1) // (-step))


SINOVLAR = [
    (0, 10, 1), (0, 10, 3), (0, 10, 4),
    (10, 0, -1), (10, 0, -3), (5, 5, 1), (5, 0, 1),
]

print(f"  {'range':<20} {'len()':>7} {'formula':>9}")
print("  " + "─" * 38)
for start, stop, step in SINOVLAR:
    haqiqiy = len(range(start, stop, step))
    hisoblangan = range_uzunlik(start, stop, step)
    assert haqiqiy == hisoblangan
    print(f"  range({start}, {stop}, {step}){'':<8} {haqiqiy:>7} {hisoblangan:>9}")


print("\n\n=== 4. ⭐ `in` — O(1) ===")

katta = range(100_000_000)
royxat = list(range(200_000))

boshlandi = time.perf_counter()
for _ in range(1000):
    99_999_999 in katta
vaqt_range = time.perf_counter() - boshlandi

boshlandi = time.perf_counter()
for _ in range(1000):
    199_999 in royxat
vaqt_royxat = time.perf_counter() - boshlandi

print(f"  1000 ta tekshiruv:")
print(f"    range (100M element):  {vaqt_range * 1000:>10.3f} ms")
print(f"    ro'yxat (200K):        {vaqt_royxat * 1000:>10.3f} ms")
print(f"    Farq: {vaqt_royxat / vaqt_range:,.0f}x")

print("\n  range matematik hisob qiladi:")
print("""
    def range_in(x, r):
        if not (r.start <= x < r.stop):
            return False
        return (x - r.start) % r.step == 0
""")


print("=== 5. Kesim range qaytaradi ===")

r = range(0, 100, 5)
kesimlar = [
    ("r[10:20]",  r[10:20]),
    ("r[::2]",    r[::2]),
    ("r[::-1]",   r[::-1]),
    ("r[5:]",     r[5:]),
    ("r[:5]",     r[:5]),
]

print(f"  r = range(0, 100, 5)\n")
for kod, natija in kesimlar:
    elementlar = list(natija)[:5]
    davomi = "..." if len(natija) > 5 else ""
    print(f"  {kod:<12} → {natija!s:<24} {elementlar}{davomi}")


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

juftliklar = [
    ("range(5) == range(5)",            range(5) == range(5)),
    ("range(0,5) == range(0,5,1)",      range(0, 5) == range(0, 5, 1)),
    ("range(0) == range(5,5)",          range(0) == range(5, 5)),
    ("range(0,5,2) == range(0,6,2)",    range(0, 5, 2) == range(0, 6, 2)),
    ("range(1,5) == range(1,6)",        range(1, 5) == range(1, 6)),
]

for kod, natija in juftliklar:
    print(f"  {kod:<34} {natija}")

print("\n  range ELEMENTLARI bo'yicha solishtiriladi:")
print(f"    list(range(0,5,2)) = {list(range(0, 5, 2))}")
print(f"    list(range(0,6,2)) = {list(range(0, 6, 2))}  ← bir xil!")


print("\n\n=== 7. Katta sonlar ===")

r = range(10 ** 18)
print(f"  r = range(10**18)")
print(f"    len(r)          = {len(r):,}")
print(f"    r[999_999_999]  = {r[999_999_999]:,}")
print(f"    10**15 in r     = {10 ** 15 in r}")
print(f"    sys.getsizeof   = {sys.getsizeof(r)} bayt")
print("\n  ⚠️ list(range(10**18)) — xotira yetmaydi!")

Natijaning muhim qismi:

text
=== 1. Xotira ===
              Hajm        range             list
  ────────────────────────────────────────────────
                10           48              136
             1,000           48            8,056
         1,000,000           48        8,000,056
 1,000,000,000,000           48 (xotira yetmaydi)

=== 4. ⭐ `in` — O(1) ===
  1000 ta tekshiruv:
    range (100M element):       0.187 ms
    ro'yxat (200K):          1847.320 ms
    Farq: 9,878x

=== 6. Solishtirish ===
  range(5) == range(5)               True
  range(0,5) == range(0,5,1)         True
  range(0) == range(5,5)             True
  range(0,5,2) == range(0,6,2)       True
  range(1,5) == range(1,6)           False

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

Misol 2 — Manfiy qadam va teskari yurish

python
"""range bilan teskari yurish."""

print("=== 1. ⭐ Manfiy qadamda 0 tuzog'i ===")

variantlar = [
    ("range(5, 0, -1)",   range(5, 0, -1)),
    ("range(5, -1, -1)",  range(5, -1, -1)),
    ("range(0, -5, -1)",  range(0, -5, -1)),
    ("range(10, 0, -2)",  range(10, 0, -2)),
    ("range(10, -1, -2)", range(10, -1, -2)),
]

for kod, r in variantlar:
    nolm = "  ← 0 bor" if 0 in r else "  ← 0 YO'Q"
    print(f"  {kod:<20} → {list(r)}{nolm}")

print("\n  `stop` KIRMAYDI qoidasi manfiy qadamda ham amal qiladi")


print("\n\n=== 2. Ro'yxatni teskari bo'ylab ===")

royxat = ["a", "b", "c", "d", "e"]
print(f"  Ro'yxat: {royxat}\n")

usullar = [
    ("reversed(royxat)",
     list(reversed(royxat))),
    ("royxat[::-1]",
     royxat[::-1]),
    ("[royxat[i] for i in range(len(royxat)-1, -1, -1)]",
     [royxat[i] for i in range(len(royxat) - 1, -1, -1)]),
    ("[royxat[i] for i in reversed(range(len(royxat)))]",
     [royxat[i] for i in reversed(range(len(royxat)))]),
]

for kod, natija in usullar:
    print(f"  {kod}")
    print(f"    → {natija}\n")

print("  ✅ Eng idiomatik: reversed(royxat)")


print("=== 3. Indeks bilan teskari ===")

print("  ❌ Chalkash:")
for i in range(len(royxat) - 1, -1, -1):
    print(f"    {i}: {royxat[i]}", end="")
print()

print("\n  ✅ reversed(range(...)):")
for i in reversed(range(len(royxat))):
    print(f"    {i}: {royxat[i]}", end="")
print()

print("\n  ✅ enumerate + reversed:")
for i, x in reversed(list(enumerate(royxat))):
    print(f"    {i}: {x}", end="")
print()


print("\n\n=== 4. Teskari yurish — o'chirish uchun ===")

sonlar = [1, 2, 4, 5, 6, 8, 9, 10]            # ⚠️ juftlar YONMA-YON
print(f"  Asl: {sonlar}")
print("  Maqsad: juft sonlarni o'chirish\n")

# ❌ Oldinga yurish
sinov = sonlar[:]
for i in range(len(sinov)):
    if i < len(sinov) and sinov[i] % 2 == 0:
        del sinov[i]
print(f"  ❌ Oldinga:  {sinov}")

# ✅ Teskari
sinov = sonlar[:]
for i in range(len(sinov) - 1, -1, -1):
    if sinov[i] % 2 == 0:
        del sinov[i]
print(f"  ✅ Teskari:  {sinov}")

# ✅✅ Generator
sinov = [x for x in sonlar if x % 2 != 0]
print(f"  ✅ Generator: {sinov}")

print("\n  Teskari yurishda o'chirish indekslarni buzmaydi")
print("  (chunki o'chirilgan elementdan KEYINGILAR siljiydi)")


print("\n\n=== 5. Sanoq — teskari ===")

print("  Raketa uchirish:")
for i in range(5, 0, -1):
    print(f"    {i}...")
print("    🚀 Uchdi!")

print("\n  Sanoq 0 dan:")
for i in range(5, -1, -1):
    print(f"    {i}", end="")
print()

Natijaning muhim qismi:

text
=== 1. ⭐ Manfiy qadamda 0 tuzog'i ===
  range(5, 0, -1)      → [5, 4, 3, 2, 1]  ← 0 YO'Q
  range(5, -1, -1)     → [5, 4, 3, 2, 1, 0]  ← 0 bor
  range(0, -5, -1)     → [0, -1, -2, -3, -4]  ← 0 bor
  range(10, 0, -2)     → [10, 8, 6, 4, 2]  ← 0 YO'Q
  range(10, -1, -2)    → [10, 8, 6, 4, 2, 0]  ← 0 bor

=== 4. Teskari yurish — o'chirish uchun ===
  Asl: [1, 2, 4, 5, 6, 8, 9, 10]
  Maqsad: juft sonlarni o'chirish

  ❌ Oldinga:  [1, 4, 5, 8, 9]
  ✅ Teskari:  [1, 5, 9]
  ✅ Generator: [1, 5, 9]

Nima ko'rsatdi: 2.4-bo'lim.

Misol 3 — Kasr sonlar va muqobillar

python
"""range faqat butun sonlar bilan ishlaydi."""

from decimal import Decimal
from itertools import count, islice

print("=== 1. ❌ Kasr bilan ishlamaydi ===")
try:
    range(0, 1, 0.1)
except TypeError as x:
    print(f"  range(0, 1, 0.1) → TypeError: {x}")


print("\n\n=== 2. ✅ Butun sonlar bilan sanash ===")

n = 10
qiymatlar = [i / n for i in range(n)]
print(f"  [i/10 for i in range(10)]:")
print(f"    {qiymatlar}")
print(f"    Aniqmi? {all(round(x * 10) == i for i, x in enumerate(qiymatlar))}")


print("\n\n=== 3. frange generatori ===")


def frange(start: float, stop: float, step: float = 1.0):
    """Kasr sonli diapazon.

    start + i * step ishlatiladi (x += step emas) — xato to'planmaydi.
    """
    if step == 0:
        raise ValueError("step nol bo'lishi mumkin emas")

    n = int(round((stop - start) / step))
    for i in range(max(0, n)):
        yield start + i * step


print(f"  frange(0, 1, 0.25):  {list(frange(0, 1, 0.25))}")
print(f"  frange(0, 1, 0.1):   {[round(x, 10) for x in frange(0, 1, 0.1)]}")
print(f"  frange(1, 0, -0.25): {list(frange(1, 0, -0.25))}")


print("\n\n=== 4. ⚠️ Xato to'planishi ===")

print("  ❌ x += step (xato to'planadi):")
x = 0.0
yomon = []
for _ in range(10):
    yomon.append(x)
    x += 0.1

print(f"    {[round(v, 17) for v in yomon[-3:]]}")

print("\n  ✅ start + i * step (xato to'planmaydi):")
yaxshi = [0.0 + i * 0.1 for i in range(10)]
print(f"    {[round(v, 17) for v in yaxshi[-3:]]}")

print(f"\n  Farq: {[abs(a - b) for a, b in zip(yomon[-3:], yaxshi[-3:])]}")


print("\n\n=== 5. Decimal bilan aniq ===")


def drange(start: str, stop: str, step: str):
    """Decimal bilan aniq diapazon."""
    x = Decimal(start)
    stop_d = Decimal(stop)
    step_d = Decimal(step)

    while (x < stop_d) if step_d > 0 else (x > stop_d):
        yield x
        x += step_d


print(f"  drange('0', '1', '0.1'):")
print(f"    {[str(x) for x in drange('0', '1', '0.1')]}")
print("    ← Aniq! Kasr xatosi yo'q (3.4-dars)")


print("\n\n=== 6. itertools.count — cheksiz ===")

print(f"  islice(count(), 5):        {list(islice(count(), 5))}")
print(f"  islice(count(10, 5), 5):   {list(islice(count(10, 5), 5))}")
print(f"  islice(count(0, 0.25), 5): {list(islice(count(0, 0.25), 5))}")
print("\n  ⭐ count kasr qadamni QO'LLAB-QUVVATLAYDI")

print("\n  Cheksiz siklda break bilan:")
for i in count(100, -7):
    if i < 70:
        break
    print(f"    {i}", end="")
print()


print("\n\n=== 7. Solishtirish jadvali ===")

print(f"  {'Vosita':<20} {'Kasr':>6} {'Cheksiz':>9} {'Xotira':>10} {'Teskari':>9}")
print("  " + "─" * 60)
print(f"  {'range':<20} {'❌':>6} {'❌':>9} {'O(1)':>10} {'✅':>9}")
print(f"  {'itertools.count':<20} {'✅':>6} {'✅':>9} {'O(1)':>10} {'✅':>9}")
print(f"  {'frange (generator)':<20} {'✅':>6} {'❌':>9} {'O(1)':>10} {'✅':>9}")
print(f"  {'np.arange':<20} {'✅':>6} {'❌':>9} {'O(n)':>10} {'✅':>9}")
print(f"  {'np.linspace':<20} {'✅':>6} {'❌':>9} {'O(n)':>10} {'✅':>9}")


print("\n\n=== 8. NumPy (24-qism) ===")
try:
    import numpy as np

    print(f"  np.arange(0, 1, 0.25):  {np.arange(0, 1, 0.25)}")
    print(f"  np.linspace(0, 1, 5):   {np.linspace(0, 1, 5)}")
    print("\n  Farqi:")
    print("    arange   — QADAM beriladi, oxirgi qiymat kirmaydi")
    print("    linspace — SONI beriladi, oxirgi qiymat KIRADI")
except ImportError:
    print("  (numpy o'rnatilmagan: pip install numpy)")

Natijaning muhim qismi:

text
=== 4. ⚠️ Xato to'planishi ===
  ❌ x += step (xato to'planadi):
    [0.7, 0.7999999999999999, 0.8999999999999999]

  ✅ start + i * step (xato to'planmaydi):
    [0.7000000000000001, 0.8, 0.9]

  Farq: [1.1102230246251565e-16, 1.1102230246251565e-16, ...]

=== 6. itertools.count — cheksiz ===
  islice(count(), 5):        [0, 1, 2, 3, 4]
  islice(count(10, 5), 5):   [10, 15, 20, 25, 30]
  islice(count(0, 0.25), 5): [0, 0.25, 0.5, 0.75, 1.0]

  ⭐ count kasr qadamni QO'LLAB-QUVVATLAYDI

  Cheksiz siklda break bilan:
    100    93    86    79    72

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

Misol 4 — Amaliy naqshlar

python
"""range bilan tipik masalalar."""

import time
from itertools import pairwise

print("=== 1. Bo'laklarga bo'lish ===")


def boklarga_bol(ketma_ketlik, hajm: int):
    """Ketma-ketlikni teng bo'laklarga bo'ladi."""
    for i in range(0, len(ketma_ketlik), hajm):
        yield ketma_ketlik[i:i + hajm]


MALUMOT = list(range(1, 12))
print(f"  Manba: {MALUMOT}\n")

for hajm in [3, 4, 5]:
    bolaklar = list(boklarga_bol(MALUMOT, hajm))
    print(f"  hajm={hajm}: {bolaklar}")


print("\n\n=== 2. Ketma-ket juftliklar ===")

royxat = [10, 25, 18, 40, 32]
print(f"  Ro'yxat: {royxat}\n")

print("  range bilan:")
for i in range(len(royxat) - 1):
    a, b = royxat[i], royxat[i + 1]
    ozgarish = b - a
    belgi = "↑" if ozgarish > 0 else "↓"
    print(f"    {a:>3} → {b:>3}  {belgi} {abs(ozgarish):>3}")

print("\n  itertools.pairwise bilan (3.10+):")
for a, b in pairwise(royxat):
    print(f"    {a:>3} → {b:>3}")


print("\n\n=== 3. Ko'paytirish jadvali ===")

N = 5
print("      " + "".join(f"{j:>5}" for j in range(1, N + 1)))
print("     " + "─" * (5 * N + 1))
for i in range(1, N + 1):
    print(f"  {i:>2} │" + "".join(f"{i * j:>5}" for j in range(1, N + 1)))


print("\n\n=== 4. Uchburchak naqshlar ===")

N = 5

print("  To'g'ri uchburchak:")
for i in range(1, N + 1):
    print("    " + "*" * i)

print("\n  Teskari:")
for i in range(N, 0, -1):
    print("    " + "*" * i)

print("\n  Piramida:")
for i in range(1, N + 1):
    bosh_joy = " " * (N - i)
    yulduz = "*" * (2 * i - 1)
    print(f"    {bosh_joy}{yulduz}")

print("\n  Romb:")
for i in range(1, N + 1):
    print(f"    {' ' * (N - i)}{'*' * (2 * i - 1)}")
for i in range(N - 1, 0, -1):
    print(f"    {' ' * (N - i)}{'*' * (2 * i - 1)}")


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

A = [[1, 2, 3], [4, 5, 6]]
B = [[7, 8], [9, 10], [11, 12]]

print(f"  A ({len(A)}×{len(A[0])}): {A}")
print(f"  B ({len(B)}×{len(B[0])}): {B}\n")

# Transpozitsiya
print("  A transpozitsiyasi:")
At = [[A[i][j] for i in range(len(A))] for j in range(len(A[0]))]
for qator in At:
    print(f"    {qator}")

print("\n  Yoki zip bilan (9-dars):")
print(f"    {[list(q) for q in zip(*A)]}")

# Ko'paytirish
print("\n  A × B:")
natija = [
    [sum(A[i][k] * B[k][j] for k in range(len(B)))
     for j in range(len(B[0]))]
    for i in range(len(A))
]
for qator in natija:
    print(f"    {qator}")


print("\n\n=== 6. Sanash naqshlari ===")

print("  N marta takrorlash:")
for _ in range(3):
    print("    Salom", end="")
print()

print("\n  Har 10-element:")
malumot = list(range(0, 50))
print(f"    {[malumot[i] for i in range(0, len(malumot), 10)]}")
print(f"    Yoki kesim: {malumot[::10]}")

print("\n  Oxirgi 5 element (teskari):")
print(f"    {[malumot[i] for i in range(len(malumot) - 1, len(malumot) - 6, -1)]}")
print(f"    Yoki kesim: {malumot[:-6:-1]}")


print("\n\n=== 7. Tezlik: sikl vs formula ===")

N = 5_000_000

boshlandi = time.perf_counter()
jami1 = 0
for i in range(N):
    jami1 += i
vaqt_sikl = time.perf_counter() - boshlandi

boshlandi = time.perf_counter()
jami2 = sum(range(N))
vaqt_sum = time.perf_counter() - boshlandi

boshlandi = time.perf_counter()
jami3 = N * (N - 1) // 2
vaqt_formula = time.perf_counter() - boshlandi

assert jami1 == jami2 == jami3

print(f"  0 dan {N:,} gacha yig'indi = {jami1:,}\n")
print(f"  for sikli:  {vaqt_sikl * 1000:>12.3f} ms")
print(f"  sum(range): {vaqt_sum * 1000:>12.3f} ms  "
      f"({vaqt_sikl / vaqt_sum:.1f}x tezroq)")
print(f"  Formula:    {vaqt_formula * 1000:>12.6f} ms  "
      f"({vaqt_sikl / max(vaqt_formula, 1e-9):,.0f}x tezroq)")

print("\n  ⭐ Sikl kerak bo'lmasa — ishlatmang!")

Natijaning muhim qismi:

text
=== 4. Uchburchak naqshlar ===
  Piramida:
        ****
       *****
      *******
     *********
    *********

=== 5. Matritsa amallari ===
  A × B:
    [58, 64]
    [139, 154]

=== 7. Tezlik: sikl vs formula ===
  0 dan 5,000,000 gacha yig'indi = 12,499,997,500,000

  for sikli:       187.432 ms
  sum(range):       42.183 ms  (4.4x tezroq)
  Formula:           0.000234 ms  (800,991x tezroq)

Nima ko'rsatdi: 2.7, 2.8-bo'limlar.


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

Noto'g'ri fikr To'g'risi
"range ro'yxat qaytaradi" Alohida tur. list(range(...)) kerak
"range(5) — 1..5" 0..4. stop kirmaydi
"range(5, 0, -1) 0 ni ham beradi" Yo'q — range(5, -1, -1) kerak
"range(0, 1, 0.1) ishlaydi" TypeError — faqat butun sonlar
"in range da O(n)" O(1) — matematik hisob
"range bir martalik" Qayta ishlatiladi (generator emas)
"range(10**18) xotira yeydi" 48 bayt. list() esa — yo'q
"range(len(x)) normal" enumerate idiomatik
"range kesimi ro'yxat" range qaytaradi

6. Keng tarqalgan xatolar va yechimlari

1. Off-by-one

python
for i in range(1, 10):              # ❌ 1..9
for i in range(1, 11):              # ✅ 1..10

2. Manfiy qadamda 0

python
range(5, 0, -1)                     # ❌ 0 yo'q
range(5, -1, -1)                    # ✅

3. Kasr qadam

python
range(0, 1, 0.1)                    # ❌ TypeError
[i / 10 for i in range(10)]         # ✅
np.arange(0, 1, 0.1)                # ✅

4. range(len(x))

python
for i in range(len(royxat)):        # ⚠️
    print(royxat[i])

for x in royxat:                    # ✅
for i, x in enumerate(royxat):      # ✅

5. Katta range ni ro'yxatga

python
list(range(10 ** 9))                # ❌ ~8 GB
for i in range(10 ** 9): ...        # ✅

6. range ni o'zgartirishga urinish

python
r = range(5)
r[0] = 10                           # ❌ TypeError
royxat = list(r)                    # ✅

7. step=0

python
range(0, 5, 0)                      # ❌ ValueError

8. Kasr xatosi to'planishi

python
x = 0.0
while x < 1:
    x += 0.1                        # ❌ xato to'planadi

[i * 0.1 for i in range(10)]        # ✅

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 5.6-dars (o'tilgan): for sikli
  • 5.8-dars: enumerate — range(len()) o'rniga
  • 5.11-dars: ichma-ich sikllar
  • 4.2-dars (o'tilgan): kesimlar — bir xil stop qoidasi
  • 6-qism: ro'yxat generatorlari
  • 15-qism: itertools.count, islice
  • 31-qism: algoritmlar — indeks bilan ishlash
  • 24-qism: NumPy — arange, linspace

8. Eng yaxshi amaliyotlar

  1. stop kirmasligini eslang. range(1, 11) — 1 dan 10 gacha.

  2. range(len(x)) o'rniga enumerate. Idiomatik va xatosiz.

  3. Manfiy qadamda stop ni -1 qiling. range(n-1, -1, -1).

  4. Teskari yurish uchun reversed(). range(len(x)-1, -1, -1) dan aniqroq.

  5. Kasr uchun butun sonlarda sanang. i / n, start + i * step.

  6. Katta diapazonni ro'yxatga aylantirmang. range o'zi xotira ishlatmaydi.

  7. in range da tez ekanini eslang. Diapazon tekshiruvi uchun ishlatish mumkin.

  8. Sikl kerak bo'lmasa — formula. sum(range(n)) o'rniga n*(n-1)//2.


9. Amaliy topshiriq

Vazifa 1: Natijani bashorat qiling

python
1.  list(range(5))
2.  list(range(1, 5))
3.  list(range(0, 10, 3))
4.  list(range(5, 0, -1))
5.  list(range(5, -1, -1))
6.  list(range(0, 5, -1))
7.  len(range(0, 10, 3))
8.  range(0, 5, 2) == range(0, 6, 2)
9.  5 in range(0, 10, 2)
10. 6 in range(0, 10, 2)
11. list(range(10)[2:5])
12. type(range(5)[1:3])
Javoblar
  1. [0, 1, 2, 3, 4]
  2. [1, 2, 3, 4]
  3. [0, 3, 6, 9]
  4. [5, 4, 3, 2, 1]
  5. [5, 4, 3, 2, 1, 0]
  6. []
  7. 4
  8. True
  9. False — 5 toq
  10. True
  11. [2, 3, 4]
  12. <class 'range'>

Vazifa 2: range yozing

Quyidagi ketma-ketliklarni hosil qiling:

text
1.  [0, 1, 2, 3, 4, 5]
2.  [1, 3, 5, 7, 9]
3.  [10, 8, 6, 4, 2, 0]
4.  [100, 90, 80, ..., 10]
5.  [-5, -4, -3, -2, -1, 0]
6.  [0, 25, 50, 75, 100]
Javoblar
python
1.  range(6)
2.  range(1, 10, 2)
3.  range(10, -1, -2)
4.  range(100, 0, -10)
5.  range(-5, 1)
6.  range(0, 101, 25)

Vazifa 3: frange

3-misoldagi frange ni kengaytiring:

  1. Manfiy qadamni qo'llab-quvvatlasin
  2. len() ni qo'llab-quvvatlasin (sinf sifatida)
  3. Indekslashni qo'llab-quvvatlasin
  4. in operatorini qo'llab-quvvatlasin

Vazifa 4: Naqshlar

Yozing (faqat range va print bilan):

text
1.  Shaxmat taxtasi (8×8, ■ va □)
2.  Paskal uchburchagi (5 qator)
3.  Spiral matritsa (4×4)
4.  Soat yo'nalishi bo'yicha aylanma

Vazifa 5: Bo'laklarga bo'lish

boklarga_bol ni kengaytiring:

  1. toldirish parametri — oxirgi bo'lakni to'ldirish
  2. qoldiq parametri — to'liq bo'lmagan bo'lakni tashlash
  3. Generator emas, ro'yxat qaytaruvchi variant
  4. itertools.batched (3.12+) bilan solishtiring

Vazifa 6: Diapazon tekshiruvi

range ning O(1) in xususiyatidan foydalanib:

  1. HTTP_MUVAFFAQIYAT = range(200, 300) — holat kodlari
  2. KATTA_HARF = range(65, 91) — ASCII
  3. Funksiya: kod_turi(kod) → "muvaffaqiyat", "yo'naltirish", "mijoz xatosi", "server xatosi"

Vazifa 7: O'ylash

Nega range ro'yxat emas, alohida tur?

Javob

Python 2 da range ro'yxat qaytarardi:

python
# Python 2
range(5)                # [0, 1, 2, 3, 4]  — ro'yxat
xrange(5)               # generator kabi obyekt

xrange — xotira tejash uchun qo'shilgan edi.

Python 3 da range = eski xrange, chunki:

1. Xotira. for i in range(10**9) — Python 2 da 8 GB kerak bo'lardi. Python 3 da — 48 bayt.

2. Kam kerak. range natijasi 95% holatda faqat for da ishlatiladi — ro'yxat kerak emas.

3. list() bor. Kerak bo'lsa — list(range(5)). Aniq va ko'rinadigan.

Nega generator emas, alohida tur?

Chunki range ketma-ketlik protokolini qo'llab-quvvatlaydi:

python
r = range(100)
len(r)              # ✅ generator qila olmaydi
r[50]               # ✅ generator qila olmaydi
r[10:20]            # ✅ generator qila olmaydi
50 in r             # ✅ O(1), generator O(n)
reversed(r)         # ✅
list(r); list(r)    # ✅ qayta ishlatiladi

Generator bularning hech birini qila olmaydi.

range — "dangasa ketma-ketlik": elementlar saqlanmaydi, lekin ketma-ketlik kabi ishlaydi.

Bu — Pythondagi yagona bunday tur emas. dict.keys(), dict.values() va dict.items() ham shunday "ko'rinish" (view) obyektlari (6-qism).

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


Xulosa

Bu darsda range() ni chuqur o'rgandik.

Eng muhim uch fikr:

  1. range — ro'yxat emas, alohida tur. U faqat start, stop, step ni saqlaydi va elementlarni hisoblaydi. Shuning uchun range(10**18) ham 48 bayt egallaydi va in O(1) ishlaydi.

  2. stop kirmaydi — manfiy qadamda ham. range(5, 0, -1) → [5,4,3,2,1], 0 yo'q. Nolgacha borish uchun range(5, -1, -1).

  3. Faqat butun sonlar. Kasr uchun butun sonlarda sanang (i / n) yoki start + i * step formulasini ishlating — bu xato to'planishini oldini oladi.

Keyingi darsda enumerate() ni o'rganamiz — range(len(x)) ning idiomatik almashtiruvchisi va Pythonning eng foydali ichki funksiyalaridan biri.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
5.7-dars: range() chuqur — IlmHamroh