1-qism · Poydevor·02-bob
O'zgaruvchilar, obyektlar va asosiy tiplar
Python'da 'hamma narsa obyekt' degani nima, o'zgaruvchi aslida nom ekanligi, mutable va immutable tiplar, int, float, bool, None va sonlar bilan ishlashdagi tuzoqlar.
Bu bob — butun kursning eng muhim boblaridan biri. Sababi: Python'da o'zgaruvchilar boshqa ko'p tillardagidek ishlamaydi va buni tushunmaslik eng ko'p uchraydigan, eng qiyin topiladigan xatolarga olib keladi. Masalan, ML kodida "nega mening asl ma'lumotlarim o'zgarib qoldi?" degan savolning 90% javobi shu bobda.
O'zgaruvchilar "quti" emas, obyektga yopishtirilgan "yorliq" ekanini animatsiyalar bilan ko'rsatadi — bu bobning eng muhim g'oyasi (2-bo'lim).
1. Hamma narsa — obyekt#
Python'da har bir qiymat — obyekt: son, matn, ro'yxat, funksiya, klass, hatto modul ham. Har bir obyektning uchta xususiyati bor:
| Xususiyat | Nima | Qanday ko'rish mumkin | O'zgaradimi? |
|---|---|---|---|
| Identifikator (identity) | Obyektning xotiradagi "manzili" | id(x) | Hech qachon |
| Tip (type) | Obyekt qanday turdagi va nima qila oladi | type(x) | Hech qachon |
| Qiymat (value) | Obyekt ichidagi ma'lumot | print(x) | Faqat mutable obyektlarda |
>>> x = 42
>>> id(x)
4354771528 # sizda boshqa son chiqadi
>>> type(x)
<class 'int'>
>>> type(print)
<class 'builtin_function_or_method'>
>>> type(int)
<class 'type'> # klass ham obyekt — uning tipi 'type'2. O'zgaruvchi — bu quti emas, yorliq#
Ko'p darsliklar o'zgaruvchini "qiymat solinadigan quti" deb tushuntiradi. C tilida bu to'g'ri. Python'da esa bu noto'g'ri va xavfli tasavvur.
Python'da o'zgaruvchi — bu obyektga yopishtirilgan nom (yorliq,
havola). x = 42 degani: "xotirada 42 obyektini yarat (yoki top) va
unga x degan yorliqni yopishtir".
Buning oqibati — mana bu klassik "tuzoq":
a = [1, 2, 3]
b = a # NUSXA EMAS! b — o'sha ro'yxatga ikkinchi yorliq
b.append(4)
print(a) # [1, 2, 3, 4] ← a ham "o'zgardi"
print(a is b) # True — bitta obyektb = a hech qachon nusxa yaratmaydi. U shunchaki a ishora qilayotgan
obyektga yana bitta nom beradi. Ro'yxat bitta — nomlar ikkita.
Endi solishtiring:
a = [1, 2, 3]
b = a
b = [9, 9] # b'ni BOSHQA obyektga ko'chirdik — a'ga ta'sir yo'q
print(a) # [1, 2, 3]Farq nimada? b.append(4) — obyektni o'zgartirdi (mutatsiya).
b = [9, 9] — nomni boshqa obyektga ko'chirdi (qayta bog'lash,
rebinding). Bu ikki amalni farqlash — Python'ni tushunishning kaliti.
- Nom boshqa obyektga ishora qila boshlaydi
- Eski obyekt o'zgarmaydi
- Boshqa nomlarga ta'sir qilmaydi
- Misol: x = x + 1, s = s.upper()
- Obyektning o'zi o'zgaradi
- Shu obyektga ishora qiluvchi BARCHA nomlar o'zgarishni ko'radi
- Faqat mutable obyektlarda mumkin
- Misol: lst.append(1), d['k'] = 2, lst[0] = 5
Savol bering: 'men nomni ko'chiryapmanmi yoki obyektni o'zgartiryapmanmi?'
is va == farqi#
a == b— qiymatlar tengmi? (__eq__metodini chaqiradi)a is b— bitta obyektmi? (id(a) == id(b)bilan bir xil)
x = [1, 2, 3]
y = [1, 2, 3]
print(x == y) # True — qiymatlari bir xil
print(x is y) # False — ikki xil obyekt
z = x
print(x is z) # TrueQoida: isni faqat None, True, False bilan solishtirishda
ishlating (if x is None:). Qolgan hamma joyda ==.
3. Mutable va immutable#
Bu Python'ning eng muhim tushunchalaridan biri:
| Immutable (o'zgarmas) | Mutable (o'zgaruvchan) |
|---|---|
int, float, complex, bool | list |
str, bytes | dict |
tuple, frozenset | set |
None | bytearray |
| O'zingiz yozgan klasslar (odatda) |
Immutable obyektni o'zgartirib bo'lmaydi — "o'zgartirish"ga o'xshagan har qanday amal aslida yangi obyekt yaratadi:
s = "salom"
print(id(s))
s = s.upper() # yangi "SALOM" obyekti yaratildi, s unga ko'chirildi
print(id(s)) # boshqa id
n = 10
print(id(n))
n += 1 # 11 — yangi obyekt
print(id(n)) # boshqa idlst = [1, 2]
print(id(lst))
lst += [3] # list uchun += — joyida o'zgartirish (extend)
print(id(lst)) # o'sha id!Diqqat qiling: += int uchun yangi obyekt yaratadi, list uchun esa
mavjudini o'zgartiradi. Bu __iadd__ metodiga bog'liq — 13-bobda
ko'ramiz.
Nega bu ML kodida muhim?#
def normalize(data):
"""Har bir qiymatni maksimumga bo'ladi."""
m = max(data)
for i in range(len(data)):
data[i] = data[i] / m # ← asl ro'yxatni o'zgartiradi!
return data
raw = [10, 20, 40]
norm = normalize(raw)
print(norm) # [0.25, 0.5, 1.0]
print(raw) # [0.25, 0.5, 1.0] ← asl ma'lumot yo'qoldi!Funksiyaga ro'yxat berilganda nusxa emas, o'sha obyekt beriladi. Funksiya uni o'zgartirsa, chaqiruvchi ham o'zgarishni ko'radi. To'g'ri yo'l — yangi ro'yxat qaytarish:
def normalize(data):
m = max(data)
return [x / m for x in data] # yangi ro'yxat — asl ma'lumot daxlsiz4. Dinamik tiplash#
Python'da o'zgaruvchining tipi yo'q — obyektning tipi bor. Bitta nom turli vaqtda turli tipdagi obyektlarga ishora qilishi mumkin:
x = 42 # x → int
x = "qirq ikki" # x → str
x = [4, 2] # x → listBu qulay, lekin xavfli: tip xatosi faqat kod ishlaganda chiqadi.
def narx_hisobla(soni, narxi):
return soni * narxi
print(narx_hisobla(3, 1500)) # 4500
print(narx_hisobla("3", 1500)) # "333...3" — 1500 marta takrorlangan matn! Xato emas!Ikkinchi chaqiruv xato bermaydi — str * int Python'da ruxsat etilgan amal
(satrni takrorlash). Bunday xatolar jim o'tib ketadi. Shu sababli
professional kodda type hint va mypy ishlatiladi (15-bob):
def narx_hisobla(soni: int, narxi: int) -> int:
return soni * narxiPython baribir tekshirmaydi, lekin muharrir va mypy narx_hisobla("3", 1500)
ni darhol qizil chiziq bilan belgilaydi.
Kuchli tiplash. Python dinamik, lekin kuchli tiplangan: turli tiplarni
o'zi aylantirib yubormaydi. JavaScript'da "3" + 1 → "31"; Python'da →
TypeError. Bu yaxshi narsa.
5. Sonlar#
int — chegarasiz butun sonlar#
Python'da butun sonlarning chegarasi yo'q (faqat xotira):
>>> 2 ** 64
18446744073709551616
>>> 2 ** 1000 # muammosiz ishlaydi
10715086071862673209484250490600018105614048117055336074437503883703510511249...Katta sonlarni o'qish uchun _ ishlatish mumkin: 1_000_000. Boshqa sanoq
tizimlari: 0b1010 (ikkilik, 10), 0xff (o'n oltilik, 255), 0o17
(sakkizlik, 15).
Arifmetik operatorlar#
| Operator | Ma'no | Misol | Natija |
|---|---|---|---|
+ - * | Qo'shish, ayirish, ko'paytirish | 7 * 2 | 14 |
/ | Bo'lish — har doim float | 7 / 2, 6 / 2 | 3.5, 3.0 |
// | Butun bo'lish (pastga yaxlitlash) | 7 // 2, -7 // 2 | 3, -4 |
% | Qoldiq | 7 % 2, -7 % 2 | 1, 1 |
** | Daraja | 2 ** 10 | 1024 |
divmod(a, b) | (a // b, a % b) | divmod(17, 5) | (3, 2) |
E'tibor bering: -7 // 2 → -4, -3 emas. // har doim pastga
(manfiy cheksizlik tomon) yaxlitlaydi. int(-3.9) esa nolga tomon kesadi →
-3. Bu farq indekslar va batch'larni hisoblashda xatoga olib kelishi mumkin.
Amaliy misol — ma'lumotlarni batch'larga bo'lish:
n_samples = 1050
batch_size = 64
full_batches = n_samples // batch_size # 16
remainder = n_samples % batch_size # 26
n_batches = -(-n_samples // batch_size) # 17 — yuqoriga yaxlitlash hiylasi
# yoki: import math; math.ceil(n_samples / batch_size)float — va 0.1 + 0.2 muammosi#
>>> 0.1 + 0.2
0.30000000000000004
>>> 0.1 + 0.2 == 0.3
FalseBu Python xatosi emas — bu IEEE 754 standartidagi barcha tillarda
shunday (JavaScript, Java, C). Sababi: 0.1 ni ikkilik sanoq tizimida
aniq yozib bo'lmaydi (xuddi 1/3 ni o'nlik kasrda aniq yozib bo'lmagandek:
0.3333...). Kompyuter eng yaqin qiymatni saqlaydi va kichik xatolar
to'planadi.
Uchta qoida:
import math
# 1. float'larni hech qachon == bilan solishtirmang
math.isclose(0.1 + 0.2, 0.3) # True
# 2. Pul uchun Decimal ishlating
from decimal import Decimal
Decimal("0.1") + Decimal("0.2") # Decimal('0.3') — aniq
# Diqqat: Decimal(0.1) emas, Decimal("0.1") — satrdan!
# 3. Maxsus qiymatlarni biling
float("inf"), float("-inf") # cheksizlik
float("nan") # "Not a Number"
float("nan") == float("nan") # False! NaN hech narsaga teng emas, o'ziga ham
math.isnan(float("nan")) # True — NaN'ni shunday tekshiringYaxlitlash: round(2.5) → 2, round(3.5) → 4. Bu xato emas —
Python "bankir yaxlitlashi"ni (banker's rounding) ishlatadi: aniq o'rtadagi
son juft tomonga yaxlitlanadi. Bu katta hajmdagi hisob-kitoblarda
tizimli siljishni kamaytiradi.
6. bool va haqiqiylik (truthiness)#
bool — ikki qiymatli tip: True va False. Qiziq fakt: bool — intning
vorisi, True == 1, False == 0:
>>> True + True
2
>>> sum([True, False, True, True]) # nechta True borligini sanash
3Bu amalda foydali: sum(pred == true for pred, true in zip(preds, labels)) —
to'g'ri bashoratlar soni.
Truthiness. Har qanday obyektni shart sifatida ishlatish mumkin. Quyidagilar "yolg'on" (falsy) hisoblanadi — qolgan hammasi "rost" (truthy):
| Falsy qiymatlar |
|---|
False, None |
0, 0.0, 0j |
"" (bo'sh satr), [], (), {}, set(), range(0) |
ismlar = []
if ismlar: # "agar ro'yxat bo'sh bo'lmasa"
print("bor")
else:
print("bo'sh") # bo'sh7. None — "qiymat yo'q"#
None — "hech narsa", "qiymat yo'q" degan maxsus obyekt. U yagona (singleton):
butun dasturda bitta None obyekti bor, shuning uchun is bilan tekshiriladi.
def topish(ismlar, qidirilgan):
for i, ism in enumerate(ismlar):
if ism == qidirilgan:
return i
return None # topilmadi (buni yozmasangiz ham funksiya None qaytaradi)
idx = topish(["Ali", "Vali"], "Gani")
if idx is None:
print("topilmadi")return yozilmagan har qanday funksiya None qaytaradi. Klassik xato:
sonlar = [3, 1, 2]
sonlar = sonlar.sort() # sort() joyida saralaydi va None qaytaradi!
print(sonlar) # None — ro'yxat yo'qoldi8. Tiplarni aylantirish#
int("42") # 42
int(" 42\n") # 42 — bo'sh joylar e'tiborsiz
int(3.9) # 3 — kesadi, yaxlitlamaydi
int("3.9") # ValueError! Avval float("3.9"), keyin int()
int("ff", 16) # 255 — boshqa sanoq tizimidan
float("1e-3") # 0.001
str(3.14) # "3.14"
bool("False") # True! — bo'sh bo'lmagan har qanday satr truthy
list("abc") # ['a', 'b', 'c']bool("False") → True — bu ko'p odamni aldaydi. Konfiguratsiya
fayllaridan yoki muhit o'zgaruvchilaridan kelgan satrni bool'ga shunday
aylantiring:
import os
debug = os.environ.get("DEBUG", "0").lower() in {"1", "true", "yes", "on"}9. Xotira haqida qisqacha: reference counting#
CPython har bir obyektga nechta nom (havola) ishora qilayotganini sanaydi. Hisoblagich 0 ga tushganda obyekt darhol o'chiriladi:
import sys
a = [1, 2, 3]
print(sys.getrefcount(a)) # 2 (a + getrefcount argumenti)
b = a
print(sys.getrefcount(a)) # 3
del b # nomni o'chiradi, obyektni emas
print(sys.getrefcount(a)) # 2del x obyektni o'chirmaydi — faqat x nomini olib tashlaydi. Agar
obyektga boshqa havola qolmasa, keyin u o'chiriladi. Bu Jupyter'da muhim:
katta DataFrame'ni del df qilsangiz ham, agar Out[5] kabi joyda havola
qolgan bo'lsa, xotira bo'shamaydi.
Bir-biriga ishora qiluvchi obyektlar (aylana havolalar) uchun qo'shimcha
garbage collector (gc moduli) bor.
Obyekt hajmini ko'rish:
>>> import sys
>>> sys.getsizeof(1)
28 # oddiy int — 28 bayt! C'da 4-8 bayt
>>> sys.getsizeof(1.0)
24Ha, Python'da bitta son 28 bayt egallaydi — chunki u to'liq obyekt (tip ko'rsatkichi, havolalar hisoblagichi va h.k.). Million sonli ro'yxat ≈ 36 MB; NumPy massivida esa ≈ 8 MB. Yana bitta sabab — NumPy nega kerak.
10. Bir nechta tayinlash va almashtirish#
a, b = 1, 2 # bir vaqtda ikki nom
a, b = b, a # almashtirish — vaqtinchalik o'zgaruvchisiz
x = y = 0 # ikki nom bitta obyektga (int uchun xavfsiz)
# Mutable bilan ehtiyot bo'ling:
p = q = [] # p va q — BITTA ro'yxat!
p.append(1)
print(q) # [1]
birinchi, *qolgan = [1, 2, 3, 4] # birinchi=1, qolgan=[2, 3, 4]Nima noto'g'ri ketishi mumkin#
| Holat | Nima bo'ladi | To'g'risi |
|---|---|---|
b = a bilan ro'yxatni "nusxalash" | Ikki nom bitta ro'yxatga; o'zgarish ikkalasida | b = a.copy() yoki b = list(a) (5-bobda chuqur nusxa) |
| Funksiya ichida argument ro'yxatini o'zgartirish | Chaqiruvchining ma'lumoti buziladi | Yangi obyekt qaytaring |
x is 1000, s is "matn" | Ba'zan True, ba'zan False; SyntaxWarning | == ishlating |
0.1 + 0.2 == 0.3 | False | math.isclose() yoki Decimal |
x == float("nan") | Har doim False | math.isnan(x) |
value = value or default | 0, "", [] ham default'ga almashadi | if value is None: value = default |
lst = lst.sort() | lst → None | lst.sort() yoki lst = sorted(lst) |
bool("False") | True | Satrni aniq qiymatlar bilan solishtiring |
int("3.5") | ValueError | int(float("3.5")) |
1. Yorliqlarni kuzating
Quyidagi kodni bajarishdan oldin a, b, c nima bo'lishini qog'ozga
yozing, keyin tekshiring:
a = [1, 2]
b = a
c = a + [3]
b.append(4)
a = a + [5]
print(a, b, c)Maslahatni ko'rsatish
id() bilan har qadamda tekshiring. Faqat append qilingan joyda id bir xil qoladi.
2. Xavfsiz normalizatsiya
normalize(data) funksiyasini yozing: har bir qiymatni (x - min) / (max - min)
ga aylantirsin (min-max scaling), asl ro'yxatni o'zgartirmasin, hamma qiymat
bir xil bo'lsa (max == min) nolga bo'lish xatosi bermasin (hammasini 0.0
qaytarsin), bo'sh ro'yxat uchun bo'sh ro'yxat qaytarsin.
Maslahatni ko'rsatish
max() nolga teng bo'lsa nima bo'ladi? Bo'sh ro'yxat-chi?
3. Batch hisoblash
n_samples = 10_007 va batch_size = 128 uchun: nechta to'liq batch,
jami nechta batch (oxirgisi to'liq bo'lmasa ham) va oxirgi batch hajmi
qancha — faqat // va % bilan hisoblang.
Maslahatni ko'rsatish
-(-n // b) yoki math.ceil(). Oxirgi batch hajmi: n - (batches - 1) * b.
4. Muhit o'zgaruvchisini o'qish
parse_bool(value: str | None, default: bool = False) -> bool funksiyasini
yozing: "1", "true", "yes", "on" (katta-kichik harfdan qat'i nazar)
→ True; "0", "false", "no", "off" → False; None → default;
boshqa har qanday qiymat → ValueError. Bunday funksiya har bir real
loyihada kerak bo'ladi.
- 01Python'da hamma narsa obyekt; har obyektning id, tipi va qiymati bor.
- 02O'zgaruvchi — obyektga yopishtirilgan nom. b = a nusxa emas, ikkinchi nom.
- 03Mutatsiya (append, d[k] = v) obyektni o'zgartiradi va barcha nomlar buni ko'radi; = esa faqat nomni ko'chiradi.
- 04Immutable: int, float, str, tuple, None. Mutable: list, dict, set.
- 05is — bitta obyektmi; == — qiymat tengmi. is faqat None/True/False uchun.
- 06float aniq emas: math.isclose, pul uchun Decimal, NaN uchun math.isnan.
- 07// pastga yaxlitlaydi, / har doim float qaytaradi, round() juftga yaxlitlaydi.
- 08Falsy: False, None, 0, bo'sh to'plamlar. 0 ham to'g'ri qiymat bo'lsa — is None bilan tekshiring.
Mustahkamlash
Test va amaliy masalalar
Avval testni ishlang — har javobdan keyin izoh chiqadi. Keyin masalalarni shu yerning o'zida yechib, brauzerdagi haqiqiy Python bilan avtomatik tekshiring. Natijalaringiz kurs progressi sahifasida jamlanadi.
Bilimni tekshirish
Bob bo'yicha test
12 ta savol · har javobdan keyin to'g'ri yoki xatoligi va izoh ko'rsatiladi · oxirida natija foizda.
Amaliy masalalar
Kodni yozing va «Tekshirish»ni bosing (yoki Ctrl/⌘ + Enter). Kodingiz shu brauzerda saqlanib turadi.
01Min-max normalizatsiya
normalize(data) funksiyasini yozing: har bir qiymatni (x - min) / (max - min) ga aylantirgan yangi ro'yxat qaytarsin.
- Asl ro'yxat o'zgarmasin.
- Hamma qiymat bir xil bo'lsa — hammasi
0.0bo'lsin (nolga bo'lish yo'q). - Bo'sh ro'yxat uchun bo'sh ro'yxat qaytsin.
02Muhit o'zgaruvchisidan bool
parse_bool(value, default=False) funksiyasini yozing:
"1","true","yes","on"(katta-kichik harf farqsiz, chetdagi bo'sh joylar e'tiborsiz) →True"0","false","no","off"→FalseNone→default- boshqa har qanday satr →
ValueError
03Batch'lar soni
batch_info(n_samples, batch_size) funksiyasi tuple qaytarsin: (to'liq_batchlar, jami_batchlar, oxirgi_batch_hajmi). Faqat // va % operatorlaridan foydalaning. Masalan, batch_info(1050, 64) → (16, 17, 26); batch_info(128, 64) → (2, 2, 64).