IlmHamroh
Python kursi/Satrlar chuqur2/12-dars21 daqiqa
Mundarija (24)

4.2-dars: Kesimlar (slicing)

4-QISM — SATRLAR CHUQUR · 2-dars


1. Kirish va motivatsiya

Kesim — Pythonning eng chiroyli va eng ko'p ishlatiladigan imkoniyatlaridan biri.

python
matn = "Python dasturlash"

print(matn[:6])             # 'Python'
print(matn[-10:])           # 'dasturlash'
print(matn[::-1])           # teskari
print(matn[::2])            # har ikkinchisi

Boshqa ko'p tilda buning uchun funksiya chaqirish, sikl yoki kutubxona kerak. Pythonda — bitta qavs.

Lekin kesimlar ko'p savol tug'diradi:

python
print(matn[10:5])           # '' — nega bo'sh?
print(matn[::-2])           # nima bo'ladi?
print(matn[5:1:-1])         # ?
print(matn[-1:-5:-1])       # ?

Va eng chalkashtiradigan:

python
royxat = [1, 2, 3, 4, 5]
royxat[1:3] = [9]           # ro'yxatga o'zlashtirish mumkin
print(royxat)               # [1, 9, 4, 5]

matn[1:3] = "X"             # ❌ satrga mumkin emas

Bu darsda kesimlarni to'liq o'rganamiz: sintaksis, chegara qoidalari, manfiy qadam, slice obyekti va eng foydali idiomalar.


2. Nazariya — chuqur tushuntirish

2.1. Asosiy sintaksis

python
ketma_ketlik[boshi : oxiri : qadam]
Qism Ma'nosi Sukut (musbat qadam)
boshi Qaysi indeksdan 0
oxiri Qaysi indeksgacha (kirmaydi) len(x)
qadam Har nechanchisi 1
python
matn = "0123456789"

print(matn[2:5])            # '234'      — 2, 3, 4
print(matn[:5])             # '01234'
print(matn[5:])             # '56789'
print(matn[:])              # butun satr
print(matn[::2])            # '02468'
print(matn[1::2])           # '13579'
print(matn[::3])            # '0369'

2.2. Nega oxiri kirmaydi

Bu — boshida g'alati tuyuladi, lekin juda foydali.

1. Uzunlik oddiy hisoblanadi:

python
matn = "0123456789"
a, b = 2, 7
print(len(matn[a:b]) == b - a)      # True — 5

2. Bo'lish va birlashtirish:

python
n = 5
print(matn[:n] + matn[n:] == matn)  # True

Hech qanday element yo'qolmaydi va takrorlanmaydi.

3. Ketma-ket bo'laklar:

python
for i in range(0, 10, 3):
    print(matn[i:i + 3], end=" ")   # 012 345 678 9
print()

Chegaralar aniq mos keladi.

4. range bilan izchil:

python
print(list(range(2, 5)))            # [2, 3, 4]
print(matn[2:5])                    # '234'

Bir xil qoida — o'rganish oson.

Bu — Edsger Dijkstra tomonidan asoslangan yondashuv. Ko'p til (Python, Go, Rust) shu qoidani qabul qilgan.

2.3. Chegaralar avtomatik to'g'rilanadi

Indekslashdan farqli o'laroq, kesim hech qachon xato bermaydi:

python
matn = "abc"

print(matn[10])             # ❌ IndexError
print(matn[10:])            # ✅ ''
print(matn[:100])           # ✅ 'abc'
print(matn[-100:])          # ✅ 'abc'
print(matn[5:10])           # ✅ ''
print(matn[10:5])           # ✅ '' — boshi oxiridan katta

Qoida:

text
boshi  < 0        →  max(0, len + boshi)
boshi  > len      →  len
oxiri  < 0        →  max(0, len + oxiri)
oxiri  > len      →  len
boshi >= oxiri    →  bo'sh natija (musbat qadamda)

Amaliy foyda:

python
# ❌ Tekshirish kerak
if len(matn) >= 3:
    boshi = matn[0] + matn[1] + matn[2]

# ✅ Kesim o'zi hal qiladi
boshi = matn[:3]
python
# Xavfsiz birinchi belgi
birinchi = matn[:1]         # '' agar bo'sh bo'lsa
birinchi = matn[0]          # ❌ IndexError agar bo'sh bo'lsa

2.4. Manfiy indekslar

python
matn = "0123456789"

#  0  1  2  3  4  5  6  7  8  9
# -10 -9 -8 -7 -6 -5 -4 -3 -2 -1

print(matn[-3:])            # '789'
print(matn[:-3])            # '0123456'
print(matn[-5:-2])          # '567'
print(matn[-1:])            # '9'
print(matn[:-1])            # '012345678'

Foydali idiomalar:

python
print(matn[:-1])            # oxirgisisiz
print(matn[1:])             # birinchisisiz
print(matn[1:-1])           # ikkalasisiz
print(matn[-3:])            # oxirgi 3
print(matn[:3])             # birinchi 3

Tuzoq — [:-0]:

python
n = 0
print(matn[:-n])            # '' — chunki -0 == 0!

-0 0 ga teng, shuning uchun matn[:0] = bo'sh satr.

Yechim:

python
print(matn[:-n if n else None])     # butun satr
print(matn[:len(matn) - n])         # yoki shunday

None — "chegara yo'q" degani (2.7-bo'limda).

2.5. Manfiy qadam — teskari yurish

python
matn = "0123456789"

print(matn[::-1])           # '9876543210'  — teskari
print(matn[::-2])           # '97531'
print(matn[8:2:-1])         # '87654'
print(matn[-1:-5:-1])       # '9876'

Manfiy qadamda sukut qiymatlar o'zgaradi:

Qadam boshi sukut oxiri sukut
Musbat 0 len(x)
Manfiy len(x) - 1 boshidan oldin

Shuning uchun:

python
print(matn[::-1])           # '9876543210' — oxiridan boshiga
print(matn[5::-1])          # '543210'     — 5-indeksdan boshiga
print(matn[:5:-1])          # '9876'       — oxiridan 5-gacha (5 kirmaydi)

Klassik tuzoq:

python
print(matn[5:0:-1])         # '54321' — 0 KIRMAYDI!
print(matn[5::-1])          # '543210' — ✅ 0 ni ham olish uchun

oxiri=0 "0-indeksgacha, o'zi kirmaydi" degani. Boshigacha borish uchun oxiri ni tashlab ketish kerak.

Yana bir tuzoq:

python
print(matn[2:5:-1])         # '' — bo'sh!

Nega? Manfiy qadamda boshi oxiri dan katta bo'lishi kerak. 2 < 5 — hech narsa qaytmaydi.

Vizual tushuntirish:

text
matn[2:5:1]     2 → 3 → 4        ✅ oldinga yurish
matn[5:2:-1]    5 → 4 → 3        ✅ orqaga yurish
matn[2:5:-1]    2 → ? orqaga...  ❌ 5 ga yetib bo'lmaydi

2.6. Kesim algoritmi

Pythonning ichki mantiqini bilish barcha tuzoqni tushuntiradi:

python
def kesim_tushuntir(uzunlik: int, boshi=None, oxiri=None, qadam=None):
    """slice.indices() nima qilishini ko'rsatadi."""
    s = slice(boshi, oxiri, qadam)
    b, o, q = s.indices(uzunlik)
    indekslar = list(range(b, o, q))
    print(f"  [{boshi}:{oxiri}:{qadam}] → range({b}, {o}, {q}) → {indekslar}")


matn = "0123456789"
n = len(matn)

print("=== Musbat qadam ===")
kesim_tushuntir(n, 2, 5)
kesim_tushuntir(n, None, 5)
kesim_tushuntir(n, 5, None)
kesim_tushuntir(n, -3, None)
kesim_tushuntir(n, 10, 20)

print("\n=== Manfiy qadam ===")
kesim_tushuntir(n, None, None, -1)
kesim_tushuntir(n, 5, None, -1)
kesim_tushuntir(n, 5, 0, -1)
kesim_tushuntir(n, 2, 5, -1)
text
=== Musbat qadam ===
  [2:5:None] → range(2, 5, 1) → [2, 3, 4]
  [None:5:None] → range(0, 5, 1) → [0, 1, 2, 3, 4]
  [5:None:None] → range(5, 10, 1) → [5, 6, 7, 8, 9]
  [-3:None:None] → range(7, 10, 1) → [7, 8, 9]
  [10:20:None] → range(10, 10, 1) → []

=== Manfiy qadam ===
  [None:None:-1] → range(9, -1, -1) → [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
  [5:None:-1] → range(5, -1, -1) → [5, 4, 3, 2, 1, 0]
  [5:0:-1] → range(5, 0, -1) → [5, 4, 3, 2, 1]
  [2:5:-1] → range(2, 5, -1) → []

Kesim = range + indekslash. Shuni tushunsangiz, barcha xatti-harakat mantiqiy bo'ladi.

2.7. slice obyekti

Kesim aslida obyekt:

python
s = slice(2, 5)
print(s)                    # slice(2, 5, None)
print(s.start, s.stop, s.step)      # 2 5 None

matn = "0123456789"
print(matn[s])              # '234'
print(matn[2:5])            # '234' — bir xil

Nima uchun foydali?

1. Nomlangan kesimlar:

python
# Sobit kengliklarli ma'lumot (masalan, bank fayli)
ISM = slice(0, 20)
HISOB = slice(20, 40)
SUMMA = slice(40, 55)

qator = "Ali Valiyev         12345678901234567890    1500000.00"

print(f"Ism:   {qator[ISM].strip()!r}")
print(f"Hisob: {qator[HISOB].strip()!r}")
print(f"Summa: {qator[SUMMA].strip()!r}")

Kodni o'qish osonlashadi va kengliklar bir joyda.

2. Kesimni funksiyaga uzatish:

python
def qismini_ol(malumot, kesim: slice):
    return malumot[kesim]


print(qismini_ol("0123456789", slice(2, 5)))    # '234'
print(qismini_ol([1, 2, 3, 4, 5], slice(1, 3))) # [2, 3]

3. Ellipsis va ko'p o'lchovli (NumPy):

python
# NumPy da (24-qism)
# massiv[1:3, ::2]  →  (slice(1,3), slice(None,None,2))

slice.indices() — chegaralarni hisoblash:

python
s = slice(None, None, -1)
print(s.indices(10))        # (9, -1, -1)

Bu — 2.6-bo'limdagi funksiya ishlatgan usul.

2.8. Kesim boshqa turlarda

Kesim ketma-ketlik protokoli ni qo'llab-quvvatlaydigan hamma turda ishlaydi:

python
# Satr
print("0123456789"[2:5])            # '234'

# Ro'yxat
print([0,1,2,3,4,5,6,7,8,9][2:5])   # [2, 3, 4]

# Juftlik
print((0,1,2,3,4)[1:3])             # (1, 2)

# range
print(range(10)[2:5])               # range(2, 5)
print(list(range(10)[::2]))         # [0, 2, 4, 6, 8]

# bytes
print(b"0123456789"[2:5])           # b'234'

# ❌ To'plam va lug'at — indekslanmaydi
# {1,2,3}[0:2]                      # TypeError

Muhim farq — nusxa:

python
matn = "abc"
print(matn[:] is matn)              # True  — satr o'zgarmas, nusxa kerak emas

royxat = [1, 2, 3]
print(royxat[:] is royxat)          # False — YANGI ro'yxat

royxat[:] — ro'yxat nusxasini olishning klassik usuli (3.1-dars).

Ro'yxatda kesim bilan o'zlashtirish:

python
royxat = [0, 1, 2, 3, 4, 5]

royxat[1:3] = [9, 9, 9]     # uzunlik o'zgarishi mumkin!
print(royxat)               # [0, 9, 9, 9, 3, 4, 5]

royxat[::2] = [0, 0, 0, 0]  # kengaytirilgan kesim — uzunlik MOS bo'lishi kerak
print(royxat)               # [0, 9, 0, 9, 0, 4, 0]

del royxat[1:3]
print(royxat)               # [0, 9, 0, 4, 0]

Satrda bu ishlamaydi — u o'zgarmas:

python
matn = "abc"
# matn[0:1] = "X"           # ❌ TypeError
matn = "X" + matn[1:]       # ✅

6-qismda ro'yxat kesimlarini batafsil o'rganamiz.

2.9. Foydali idiomalar

python
matn = "Python dasturlash"

# Teskarilash
print(matn[::-1])

# Har ikkinchisi
print(matn[::2])

# Oxirgisisiz / birinchisisiz
print(matn[:-1])
print(matn[1:])

# Ikkala tomondan bittadan
print(matn[1:-1])

# Oxirgi N
N = 5
print(matn[-N:])

# Birinchi N (xavfsiz — uzunlik yetmasa ham ishlaydi)
print(matn[:N])

# N ta bo'laklarga bo'lish
K = 4
print([matn[i:i + K] for i in range(0, len(matn), K)])

# Prefiks/suffiks olib tashlash (Python 3.9+)
print("test_fayl.py".removeprefix("test_"))     # 'fayl.py'
print("test_fayl.py".removesuffix(".py"))       # 'test_fayl'

# 3.9 gacha bo'lgan usul (ehtiyot bilan!)
nom = "test_fayl.py"
if nom.startswith("test_"):
    print(nom[len("test_"):])

Klassik xato:

python
nom = "test_fayl.py"
print(nom.strip(".py"))         # ❌ 'test_fayl' — tasodifan to'g'ri
print("python.py".strip(".py"))  # ❌ 'thon' — boshidagi 'p', 'y' ham o'chdi!

strip() belgilar to'plamini olib tashlaydi, pastki satrni emas. removesuffix() ishlating.

Bo'laklarga bo'lish funksiyasi:

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


print(boklarga_bol("0123456789", 3))        # ['012', '345', '678', '9']
print(boklarga_bol([1,2,3,4,5], 2))         # [[1,2], [3,4], [5]]

Oxirgi bo'lak to'liq bo'lmasligi mumkin — kesim buni o'zi hal qiladi (2.3-bo'lim).

2.10. Tezlik

python
import time

matn = "a" * 1_000_000

# Kesim — O(k), k — natija uzunligi
boshlandi = time.perf_counter()
for _ in range(100):
    matn[:1000]
vaqt_kichik = time.perf_counter() - boshlandi

boshlandi = time.perf_counter()
for _ in range(100):
    matn[:]
vaqt_katta = time.perf_counter() - boshlandi

print(f"  [:1000]  {vaqt_kichik * 1000:>8.2f} ms")
print(f"  [:]      {vaqt_katta * 1000:>8.2f} ms")

Muhim: kesim yangi obyekt yaratadi va ma'lumotni nusxalaydi. Katta satrni tez-tez kesish sekin.

Nusxasiz kesim — memoryview (baytlar uchun):

python
baytlar = b"a" * 1_000_000

nusxa = baytlar[:500_000]           # nusxalaydi
korinish = memoryview(baytlar)[:500_000]    # NUSXALAMAYDI

print(type(korinish))               # <class 'memoryview'>
print(len(korinish))                # 500000

memoryview — katta ikkilik ma'lumot bilan ishlaganda foydali. 16-qismda ko'ramiz.

Satrlar uchun memoryview yo'q — lekin ko'p holatda kesim o'rniga indeks bilan ishlash mumkin:

python
# ❌ Har iteratsiyada nusxa
while matn:
    belgi = matn[0]
    matn = matn[1:]         # O(n) har safar → jami O(n²)

# ✅ Indeks bilan
for i in range(len(matn)):
    belgi = matn[i]         # O(1)

3. Tez ma'lumotnoma

Sintaksis

python
x[boshi:oxiri:qadam]

sukut (musbat qadam):  0, len(x), 1
sukut (manfiy qadam):  len(x)-1, boshidan oldin, —

Asosiy idiomalar

python
x[:]            nusxa (ro'yxat uchun)
x[::-1]         teskari
x[::2]          har ikkinchisi
x[:-1]          oxirgisisiz
x[1:]           birinchisisiz
x[1:-1]         ikkalasisiz
x[-N:]          oxirgi N
x[:N]           birinchi N (xavfsiz)

Tuzoqlar

python
x[5:0:-1]       0 KIRMAYDI → x[5::-1]
x[2:5:-1]       '' — manfiy qadamda boshi > oxiri bo'lsin
x[:-0]          '' — chunki -0 == 0
x.strip(".py")  ❌ belgilar to'plami → removesuffix(".py")

Chegaralar

text
Kesim HECH QACHON IndexError bermaydi
x[100:200] → ''
x[:1000]   → butun

slice obyekti

python
s = slice(2, 5)
x[s] ≡ x[2:5]
s.indices(len(x))   → (boshi, oxiri, qadam)

4. Batafsil misollar

Misol 1 — Kesim jadvali

python
"""Barcha kesim varianti — bir joyda."""

matn = "0123456789"
n = len(matn)

print(f"Satr: {matn!r}  (uzunlik {n})\n")

print("=== Musbat qadam ===")
variantlar = [
    ("[2:5]",       matn[2:5]),
    ("[:5]",        matn[:5]),
    ("[5:]",        matn[5:]),
    ("[:]",         matn[:]),
    ("[::2]",       matn[::2]),
    ("[1::2]",      matn[1::2]),
    ("[::3]",       matn[::3]),
    ("[2:8:2]",     matn[2:8:2]),
    ("[-3:]",       matn[-3:]),
    ("[:-3]",       matn[:-3]),
    ("[-5:-2]",     matn[-5:-2]),
    ("[1:-1]",      matn[1:-1]),
]
for yozuv, natija in variantlar:
    print(f"  {yozuv:<12} → {natija!r}")

print("\n=== Manfiy qadam ===")
variantlar = [
    ("[::-1]",      matn[::-1]),
    ("[::-2]",      matn[::-2]),
    ("[5::-1]",     matn[5::-1]),
    ("[:5:-1]",     matn[:5:-1]),
    ("[8:2:-1]",    matn[8:2:-1]),
    ("[5:0:-1]",    matn[5:0:-1]),
    ("[-1:-5:-1]",  matn[-1:-5:-1]),
    ("[2:5:-1]",    matn[2:5:-1]),
]
for yozuv, natija in variantlar:
    izoh = "  ← BO'SH!" if not natija else ""
    print(f"  {yozuv:<12} → {natija!r}{izoh}")

print("\n=== Chegaradan chiqish (xato YO'Q) ===")
variantlar = [
    ("[100:]",      matn[100:]),
    ("[:100]",      matn[:100]),
    ("[-100:]",     matn[-100:]),
    ("[50:60]",     matn[50:60]),
    ("[10:5]",      matn[10:5]),
    ("[:-0]",       matn[:-0]),
]
for yozuv, natija in variantlar:
    print(f"  {yozuv:<12} → {natija!r}")

print("\n=== Solishtirish: indeks xato beradi ===")
try:
    matn[100]
except IndexError as x:
    print(f"  matn[100]    → IndexError: {x}")
print(f"  matn[100:101] → {matn[100:101]!r}  ← xavfsiz")
text
Satr: '0123456789'  (uzunlik 10)

=== Musbat qadam ===
  [2:5]        → '234'
  [:5]         → '01234'
  [5:]         → '56789'
  [:]          → '0123456789'
  [::2]        → '02468'
  [1::2]       → '13579'
  [::3]        → '0369'
  [2:8:2]      → '246'
  [-3:]        → '789'
  [:-3]        → '0123456'
  [-5:-2]      → '567'
  [1:-1]       → '12345678'

=== Manfiy qadam ===
  [::-1]       → '9876543210'
  [::-2]       → '97531'
  [5::-1]      → '543210'
  [:5:-1]      → '9876'
  [8:2:-1]     → '87654'
  [5:0:-1]     → '54321'
  [-1:-5:-1]   → '9876'
  [2:5:-1]     → ''  ← BO'SH!

=== Chegaradan chiqish (xato YO'Q) ===
  [100:]       → ''
  [:100]       → '0123456789'
  [-100:]      → '0123456789'
  [50:60]      → ''
  [10:5]       → ''
  [:-0]        → ''

=== Solishtirish: indeks xato beradi ===
  matn[100]    → IndexError: string index out of range
  matn[100:101] → ''  ← xavfsiz

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

Misol 2 — Kesim algoritmini ochish

python
"""Kesim = range + indekslash."""


def kesim_tushuntir(ketma_ketlik, boshi=None, oxiri=None, qadam=None) -> None:
    """slice.indices() qanday ishlashini ko'rsatadi."""
    n = len(ketma_ketlik)
    s = slice(boshi, oxiri, qadam)
    b, o, q = s.indices(n)
    indekslar = list(range(b, o, q))

    natija = ketma_ketlik[boshi:oxiri:qadam]

    yozuv = f"[{boshi if boshi is not None else ''}:" \
            f"{oxiri if oxiri is not None else ''}" \
            f"{':' + str(qadam) if qadam is not None else ''}]"

    print(f"  {yozuv:<12} → range({b}, {o}, {q})")
    print(f"  {'':12}   indekslar: {indekslar}")
    print(f"  {'':12}   natija:    {natija!r}\n")


matn = "abcdefghij"
print(f"Satr: {matn!r}  (uzunlik {len(matn)})\n")

print("=== Sukut qiymatlar ===")
kesim_tushuntir(matn)
kesim_tushuntir(matn, 2, 5)
kesim_tushuntir(matn, None, None, -1)

print("=== Manfiy indekslar to'g'rilanadi ===")
kesim_tushuntir(matn, -3, None)
kesim_tushuntir(matn, None, -3)

print("=== Chegaradan chiqish qisiladi ===")
kesim_tushuntir(matn, 100, 200)
kesim_tushuntir(matn, -100, 100)

print("=== Bo'sh natija sabablari ===")
kesim_tushuntir(matn, 5, 2)
kesim_tushuntir(matn, 2, 5, -1)

print("=== 0 tuzog'i ===")
kesim_tushuntir(matn, 5, 0, -1)
kesim_tushuntir(matn, 5, None, -1)

Muhim qismi:

text
=== Sukut qiymatlar ===
  [:]          → range(0, 10, 1)
                 indekslar: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
                 natija:    'abcdefghij'

  [::-1]       → range(9, -1, -1)
                 indekslar: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
                 natija:    'jihgfedcba'

=== Bo'sh natija sabablari ===
  [5:2]        → range(5, 2, 1)
                 indekslar: []
                 natija:    ''

  [2:5:-1]     → range(2, 5, -1)
                 indekslar: []
                 natija:    ''

=== 0 tuzog'i ===
  [5:0:-1]     → range(5, 0, -1)
                 indekslar: [5, 4, 3, 2, 1]
                 natija:    'fedcb'

  [5::-1]      → range(5, -1, -1)
                 indekslar: [5, 4, 3, 2, 1, 0]
                 natija:    'fedcba'

Nima ko'rsatdi: 2.6-bo'lim. slice.indices() barcha "sehr" ni ochib beradi.

Misol 3 — Amaliy idiomalar to'plami

python
"""Kesim bilan hal qilinadigan tipik masalalar."""


def teskari(matn: str) -> str:
    return matn[::-1]


def palindrommi(matn: str) -> bool:
    toza = "".join(c.lower() for c in matn if c.isalnum())
    return toza == toza[::-1]


def boklarga_bol(ketma_ketlik, hajm: int) -> list:
    return [ketma_ketlik[i:i + hajm] for i in range(0, len(ketma_ketlik), hajm)]


def har_nechanchisi(matn: str, n: int) -> str:
    return matn[::n]


def ortasi(matn: str) -> str:
    """Satrning o'rta belgisi(lari)."""
    n = len(matn)
    return matn[(n - 1) // 2:n // 2 + 1]


def aylantir(matn: str, n: int) -> str:
    """Satrni n pozitsiyaga aylantiradi."""
    if not matn:
        return matn
    n %= len(matn)
    return matn[n:] + matn[:n]


def kartani_yashir(karta: str) -> str:
    """Karta raqamini yashiradi: 1234********5678"""
    toza = karta.replace(" ", "").replace("-", "")
    return toza[:4] + "*" * (len(toza) - 8) + toza[-4:]


def kesib_qisqartir(matn: str, uzunlik: int, oxiri: str = "…") -> str:
    """Matnni cheklaydi va oxiriga belgi qo'yadi."""
    if len(matn) <= uzunlik:
        return matn
    return matn[:uzunlik - len(oxiri)] + oxiri


print("=== Teskarilash ===")
print(f"  {teskari('Python')!r}")

print("\n=== Palindrom ===")
for m in ["radar", "A man, a plan, a canal: Panama", "salom"]:
    print(f"  {m!r:<36} → {palindrommi(m)}")

print("\n=== Bo'laklarga bo'lish ===")
print(f"  {boklarga_bol('0123456789', 3)}")
print(f"  {boklarga_bol(list(range(10)), 4)}")

print("\n=== Har nechanchisi ===")
matn = "0123456789"
for n in [1, 2, 3, -1, -2]:
    print(f"  [::{n:>2}] → {har_nechanchisi(matn, n)!r}")

print("\n=== O'rta belgi ===")
for m in ["abc", "abcd", "a", "ab"]:
    print(f"  {m!r:<8} → {ortasi(m)!r}")

print("\n=== Aylantirish ===")
for n in [0, 2, -2, 7, 12]:
    print(f"  aylantir('abcdefg', {n:>3}) → {aylantir('abcdefg', n)!r}")

print("\n=== Karta yashirish ===")
for k in ["1234 5678 9012 3456", "8600-1234-5678-9012"]:
    print(f"  {k} → {kartani_yashir(k)}")

print("\n=== Qisqartirish ===")
uzun = "Bu juda uzun matn bo'lib, uni qisqartirish kerak"
for n in [20, 30, 100]:
    print(f"  {n:>3} belgi → {kesib_qisqartir(uzun, n)!r}")

print("\n=== ⚠️ strip vs removesuffix ===")
for nom in ["test_fayl.py", "python.py", "yolboshchi.py"]:
    print(f"  {nom:<18} strip('.py')      → {nom.strip('.py')!r}")
    print(f"  {'':18} removesuffix('.py') → {nom.removesuffix('.py')!r}")
text
=== Teskarilash ===
  'nohtyP'

=== Palindrom ===
  'radar'                              → True
  'A man, a plan, a canal: Panama'     → True
  'salom'                              → False

=== Bo'laklarga bo'lish ===
  ['012', '345', '678', '9']
  [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]]

=== Har nechanchisi ===
  [:: 1] → '0123456789'
  [:: 2] → '02468'
  [:: 3] → '0369'
  [::-1] → '9876543210'
  [::-2] → '97531'

=== O'rta belgi ===
  'abc'    → 'b'
  'abcd'   → 'bc'
  'a'      → 'a'
  'ab'     → 'ab'

=== Aylantirish ===
  aylantir('abcdefg',   0) → 'abcdefg'
  aylantir('abcdefg',   2) → 'cdefgab'
  aylantir('abcdefg',  -2) → 'fgabcde'
  aylantir('abcdefg',   7) → 'abcdefg'
  aylantir('abcdefg',  12) → 'fgabcde'

=== Karta yashirish ===
  1234 5678 9012 3456 → 1234********3456
  8600-1234-5678-9012 → 8600********9012

=== Qisqartirish ===
   20 belgi → "Bu juda uzun matn b…"
   30 belgi → "Bu juda uzun matn bo'lib, un…"
  100 belgi → "Bu juda uzun matn bo'lib, uni qisqartirish kerak"

=== ⚠️ strip vs removesuffix ===
  test_fayl.py       strip('.py')      → 'test_fayl'
                     removesuffix('.py') → 'test_fayl'
  python.py          strip('.py')      → 'ython'
                     removesuffix('.py') → 'python'
  yolboshchi.py      strip('.py')      → 'yolboshchi'
                     removesuffix('.py') → 'yolboshchi'

Diqqat: "python.py".strip(".py") → 'ython' — boshidagi p ham o'chdi! strip belgilar to'plami bilan ishlaydi. Bu — juda ko'p uchraydigan xato.

Nima ko'rsatdi: 2.9-bo'lim.

Misol 4 — slice obyekti bilan sobit kenglikli fayl

python
"""Sobit kenglikli ma'lumot faylini o'qish."""

from dataclasses import dataclass
from decimal import Decimal

# Nomlangan kesimlar — kenglikllar bir joyda
HISOB_RAQAMI = slice(0, 20)
ISM = slice(20, 50)
SANA = slice(50, 58)
SUMMA = slice(58, 73)
VALYUTA = slice(73, 76)
IZOH = slice(76, None)

XOM_FAYL = """\
20208000900123456789Ali Valiyev                   07092026     1500000.00UZS To'lov
20208000900987654321Sarvarbek Abdullayev          07092026      250000.50UZS Xarid
20208000900111222333Aziza Karimova                08092026    12000000.00UZS Maosh
"""


@dataclass
class Tranzaksiya:
    hisob: str
    ism: str
    sana: str
    summa: Decimal
    valyuta: str
    izoh: str

    @classmethod
    def qatordan(cls, qator: str) -> "Tranzaksiya":
        """Sobit kenglikli qatordan obyekt yaratadi."""
        return cls(
            hisob=qator[HISOB_RAQAMI].strip(),
            ism=qator[ISM].strip(),
            sana=qator[SANA].strip(),
            summa=Decimal(qator[SUMMA].strip()),
            valyuta=qator[VALYUTA].strip(),
            izoh=qator[IZOH].strip(),
        )

    @property
    def sana_formatli(self) -> str:
        """DDMMYYYY → DD.MM.YYYY"""
        return f"{self.sana[:2]}.{self.sana[2:4]}.{self.sana[4:]}"

    @property
    def hisob_yashirilgan(self) -> str:
        """Hisob raqamini qisman yashiradi."""
        return f"{self.hisob[:4]}{'*' * 12}{self.hisob[-4:]}"


tranzaksiyalar = [
    Tranzaksiya.qatordan(q) for q in XOM_FAYL.splitlines() if q.strip()
]

print("┌─ TRANZAKSIYALAR")
print("│")
print(f"│  {'Hisob':<22} {'Ism':<24} {'Sana':<12} {'Summa':>16} {'Izoh'}")
print(f"│  {'─' * 88}")

for t in tranzaksiyalar:
    print(
        f"│  {t.hisob_yashirilgan:<22} "
        f"{t.ism:<24} "
        f"{t.sana_formatli:<12} "
        f"{t.summa:>13,.2f} {t.valyuta} "
        f"{t.izoh}"
    )

jami = sum(t.summa for t in tranzaksiyalar)
print(f"│  {'─' * 88}")
print(f"│  {'JAMI':<60} {jami:>13,.2f} UZS")
print("└─")

print("\n=== Nomlangan kesimlarning foydasi ===")
print("  Kenglikllar bir joyda — o'zgartirish oson:")
for nom, s in [("HISOB_RAQAMI", HISOB_RAQAMI), ("ISM", ISM),
               ("SANA", SANA), ("SUMMA", SUMMA)]:
    kenglik = (s.stop - s.start) if s.stop else "oxirigacha"
    print(f"    {nom:<14} slice({s.start}, {s.stop})  kenglik: {kenglik}")
text
┌─ TRANZAKSIYALAR
│
│  Hisob                  Ism                      Sana                    Summa Izoh
│  ────────────────────────────────────────────────────────────────────────────────────────
│  2020************6789   Ali Valiyev              07.09.2026        1,500,000.00 UZS To'lov
│  2020************4321   Sarvarbek Abdullayev     07.09.2026          250,000.50 UZS Xarid
│  2020************2333   Aziza Karimova           08.09.2026       12,000,000.00 UZS Maosh
│  ────────────────────────────────────────────────────────────────────────────────────────
│  JAMI                                                            13,750,000.50 UZS
└─

=== Nomlangan kesimlarning foydasi ===
  Kenglikllar bir joyda — o'zgartirish oson:
    HISOB_RAQAMI   slice(0, 20)  kenglik: 20
    ISM            slice(20, 50)  kenglik: 30
    SANA           slice(50, 58)  kenglik: 8
    SUMMA          slice(58, 73)  kenglik: 15

Nima ko'rsatdi: 2.7-bo'lim. slice obyekti bilan sobit kenglikli ma'lumot o'qish — bank, telekom va davlat tizimlarida keng tarqalgan format.


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

Noto'g'ri fikr To'g'risi
"oxiri kiritiladi" Kirmaydi. x[2:5] — 2, 3, 4
"x[100] va x[100:] bir xil" Birinchisi IndexError, ikkinchisi ''
"x[5:0:-1] boshigacha boradi" 0 kirmaydi. x[5::-1] kerak
"x[2:5:-1] teskari beradi" '' — manfiy qadamda boshi > oxiri bo'lsin
"x[:-0] butun satr" '' — chunki -0 == 0
"Kesim asl obyektga havola" Yangi obyekt — ma'lumot nusxalanadi
"x[:] — bir xil obyekt" Satrda ha, ro'yxatda yo'q (nusxa)
"strip(".py") suffiksni olib tashlaydi" Belgilar to'plamini. removesuffix() ishlating
"Kesim bepul" O(k) — natija uzunligiga mutanosib nusxalash

6. Keng tarqalgan xatolar va yechimlari

1. oxiri ni kiritilgan deb o'ylash

python
matn[0:5]                       # 5 ta belgi (0-4), 6 ta emas

2. Manfiy qadamda 0 chegarasi

python
matn[5:0:-1]                    # ❌ 0 kirmaydi
matn[5::-1]                     # ✅
matn[5::-1] == matn[:6][::-1]   # ✅ boshqa usul

3. -0 tuzog'i

python
n = 0
matn[:-n]                       # ❌ '' — chunki -0 == 0
matn[:-n or None]               # ✅ butun satr
matn[:len(matn) - n]            # ✅

4. strip bilan suffiks olib tashlash

python
"python.py".strip(".py")        # ❌ 'ython'
"python.py".removesuffix(".py") # ✅ 'python'

5. Siklda kesim — O(n²)

python
# ❌ Sekin
while matn:
    ishla(matn[0])
    matn = matn[1:]             # har safar yangi satr

# ✅ Tez
for belgi in matn:
    ishla(belgi)

6. Ro'yxat nusxasini olishni unutish

python
nusxa = royxat                  # ❌ yorliq (3.1-dars)
nusxa = royxat[:]               # ✅ nusxa
nusxa = royxat.copy()           # ✅ aniqroq

7. Kengaytirilgan kesim bilan o'zlashtirishda uzunlik

python
royxat = [0, 1, 2, 3, 4, 5]
royxat[::2] = [9, 9]            # ❌ ValueError — 3 ta o'rin, 2 ta qiymat
royxat[::2] = [9, 9, 9]         # ✅
royxat[1:3] = [9]               # ✅ oddiy kesimda uzunlik erkin

8. Emoji bilan kesish

python
matn = "Salom 👨‍👩‍👧‍👦"
matn[:8]                        # ❌ emoji buzilishi mumkin (4.1-dars)

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 4.5-dars: split/join — kesim bilan birga ishlatiladi
  • 5-qism: range — kesim bilan bir xil mantiq
  • 6-qism: ro'yxat kesimlari, kesim bilan o'zlashtirish, del
  • 6-qism: nusxa olish ([:], copy(), deepcopy())
  • 15-qism: itertools.islice — generatorlar uchun kesim
  • 16-qism: fayl va bayt kesimlari, memoryview
  • 31-qism: algoritmlar — bo'l va hukmronlik qil (arr[:mid], arr[mid:])
  • 24-qism: NumPy — ko'p o'lchovli kesimlar

8. Eng yaxshi amaliyotlar

  1. Indeks o'rniga kesim ishlating. matn[:1] matn[0] dan xavfsizroq — IndexError bermaydi.

  2. removeprefix/removesuffix ishlating. strip() belgilar to'plami bilan ishlaydi va kutilmagan natija beradi.

  3. Manfiy qadamda 0 chegarasini ehtiyot qiling. x[5::-1], x[5:0:-1] emas.

  4. Nomlangan kesimlar yarating. Sobit kenglikli ma'lumotda slice obyekti kodni ancha o'qiladigan qiladi.

  5. Siklda kesim qilmang. matn = matn[1:] — O(n²). Indeks yoki iterator ishlating.

  6. Ro'yxat nusxasi uchun .copy() afzal. [:] ishlaydi, lekin .copy() niyatni aniqroq bildiradi.

  7. slice.indices() bilan tekshiring. Shubha bo'lsa, kesim qanday range ga aylanishini ko'ring.

  8. Kesim yangi obyekt yaratishini eslang. Katta ma'lumotda bu xotira va vaqt sarfi.


9. Amaliy topshiriq

Vazifa 1: Natijani bashorat qiling

python
matn = "abcdefghij"

1.  matn[2:5]
2.  matn[:3]
3.  matn[-3:]
4.  matn[::2]
5.  matn[::-1]
6.  matn[5:0:-1]
7.  matn[5::-1]
8.  matn[2:5:-1]
9.  matn[100:]
10. matn[:-0]
11. matn[1:-1]
12. matn[::-3]
Javoblar
  1. 'cde'
  2. 'abc'
  3. 'hij'
  4. 'acegi'
  5. 'jihgfedcba'
  6. 'fedcb' — 0 kirmaydi
  7. 'fedcba'
  8. '' — manfiy qadamda 2 < 5
  9. ''
  10. '' — -0 == 0
  11. 'bcdefghi'
  12. 'jgda'

Vazifa 2: Kesim yozing

matn = "0123456789" uchun kesim yozing:

  1. '2468'
  2. '987'
  3. '13579'
  4. '0246'
  5. '86420'
  6. '123456'
Javoblar
python
1.  matn[2:9:2]
2.  matn[:6:-1]
3.  matn[1::2]
4.  matn[:7:2]
5.  matn[8::-2]
6.  matn[1:7]

Vazifa 3: Idiomalar

3-misoldagi funksiyalarni yozing (qaramasdan):

  1. teskari(matn)
  2. palindrommi(matn)
  3. boklarga_bol(x, hajm)
  4. aylantir(matn, n)

Vazifa 4: Sobit kenglikli fayl

4-misoldagi dasturni kengaytiring:

  1. Yangi ustun qo'shing: FILIAL = slice(76, 80)
  2. IZOH ni slice(80, None) ga o'zgartiring
  3. Filial bo'yicha guruhlab statistika chiqaring

Vazifa 5: Xavfsiz qisqartirish

qisqartir(matn, uzunlik) funksiyasini yozing:

  • Uzunlikdan oshsa qisqartirsin va "…" qo'shsin
  • So'z o'rtasida kesmasin — oxirgi to'liq so'zgacha
  • Bo'sh joy bilan tugamasin
python
qisqartir("Bu juda uzun matn bo'lib", 15)   # "Bu juda uzun…"
Yechim
python
def qisqartir(matn: str, uzunlik: int, oxiri: str = "…") -> str:
    if len(matn) <= uzunlik:
        return matn

    kesim = matn[:uzunlik - len(oxiri)]

    # Oxirgi bo'sh joygacha qisqartirish
    oxirgi_bosh_joy = kesim.rfind(" ")
    if oxirgi_bosh_joy > 0:
        kesim = kesim[:oxirgi_bosh_joy]

    return kesim.rstrip() + oxiri

rfind — oxiridan qidiradi (3-darsda).

Vazifa 6: Kesim algoritmi

2-misoldagi kesim_tushuntir() ni yozing va quyidagilarni tekshiring:

python
kesim_tushuntir("abcde", None, None, -1)
kesim_tushuntir("abcde", -10, 10)
kesim_tushuntir("abcde", 3, 1)

Vazifa 7: O'ylash

Nega x[5:0:-1] 0 ni o'z ichiga olmaydi, lekin x[5::-1] oladi?

Javob

oxiri doim kiritilmaydi — bu qoida musbat va manfiy qadamda bir xil ishlaydi.

python
x[5:0:-1]   →  range(5, 0, -1)   →  [5, 4, 3, 2, 1]     — 0 chegarasi
x[5::-1]    →  range(5, -1, -1)  →  [5, 4, 3, 2, 1, 0]  — chegara -1

oxiri tashlab ketilganda Python manfiy qadam uchun uni -1 deb oladi (ya'ni "0 dan ham oldin"), shuning uchun 0 kiradi.

Buni x[5:-1:-1] deb yozib bo'lmaydi — chunki -1 oxirgi indeks deb talqin qilinadi (len-1 = 9), va range(5, 9, -1) bo'sh bo'ladi.

Bu — kesimlardagi yagona haqiqiy noqulaylik. Yechim: oxiri ni tashlab keting.

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


Xulosa

Bu darsda kesimlarni to'liq o'rgandik.

Eng muhim uch fikr:

  1. oxiri hech qachon kiritilmaydi. Bu — musbat va manfiy qadamda bir xil qoida. U uzunlik hisobini (b - a) va bo'lish-birlashtirishni (x[:n] + x[n:] == x) sodda qiladi.

  2. Kesim hech qachon IndexError bermaydi. Chegaralar avtomatik qisiladi. Shuning uchun matn[:1] matn[0] dan xavfsizroq.

  3. Kesim = range + indekslash. slice.indices(len(x)) bilan har qanday kesim qanday range ga aylanishini ko'rish mumkin — barcha "sehr" shu bilan tushuntiriladi.

Keyingi darsda qidirish va tekshirish metodlarini o'rganamiz: find, index, count, startswith, in va is* oilasi.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
4.2-dars: Kesimlar (slicing) — IlmHamroh