Klass va obyekt (OOP asoslari)
Bu bobda
- klass va obyekt nima ekanini
__init__vaselfni tushunishni- atribut va metod yozishni
- atributni metod orqali xavfsiz o'zgartirishni
- OOP dagi eng ko'p uchraydigan to'rtta xatoni
Klass — chizma, obyekt — undan yasalgan narsa
Shu paytgacha ma'lumot (o'zgaruvchilar, lug'atlar) va amallar (funksiyalar) alohida yashadi. 11-bobda talabani lug'at bilan ifodalagan edik:
talaba = {"ism": "Sarvinoz", "baholar": [5, 4, 5]} def ortacha(t): return sum(t["baholar"]) / len(t["baholar"]) print(ortacha(talaba))
4.666666666666667
Ishlaydi, lekin ortacha qaysi lug'at bilan ishlashini faqat kelishuv bilan bilamiz. Obyektga yo'naltirilgan dasturlash (OOP) ma'lumot va unga tegishli amallarni bitta klass ichiga birlashtiradi.
- Klass (class) — chizma, andoza: "itning ismi va yoshi bo'ladi, u o'tira oladi".
- Obyekt (object, instance) — chizmadan yasalgan aniq narsa: "ismi Rex, yoshi 3 bo'lgan it".
Bitta chizmadan istalgancha obyekt yasash mumkin.
Birinchi klass
class It: def __init__(self, ism, yosh): self.ism = ism self.yosh = yosh def otir(self): print(f"{self.ism} o'tirdi.") def dumalash(self): print(f"{self.ism} dumaladi!") mening_itim = It("Rex", 3) print(f"Itimning ismi {mening_itim.ism}, yoshi {mening_itim.yosh} da.") mening_itim.otir() mening_itim.dumalash()
Itimning ismi Rex, yoshi 3 da. Rex o'tirdi. Rex dumaladi!
Qatorma-qator:
class It:— klass nomi. Klass nomlari KattaHarf bilan boshlanadi (CamelCase):It,Mashina,BankHisobi.def __init__(self, ism, yosh):— konstruktor. Yangi obyekt yasalganda Python uni o'zi chaqiradi. Ikki tomondagi ikkita pastki chiziq — Pythonning maxsus metodi belgisi.self— yasalayotgan obyektning o'zi.self.ism = ism— "shu obyektningismatributiga berilgan qiymatni yoz".otirvadumalash— metodlar: klass ichidagi funksiyalar. Birinchi parametri doimself.It("Rex", 3)— obyekt yasash.selfni biz bermaymiz, Python o'zi qo'yadi:"Rex"→ism,3→yosh.
Bir klass — ko'p obyekt
Har bir obyekt o'z atributlariga ega:
class It: def __init__(self, ism, yosh): self.ism = ism self.yosh = yosh def otir(self): print(f"{self.ism} o'tirdi.") rex = It("Rex", 3) mosh = It("Mosh", 6) rex.otir() mosh.otir() print(rex.yosh, mosh.yosh)
Rex o'tirdi. Mosh o'tirdi. 3 6
rex.otir() chaqirilganda self — rex; mosh.otir() da — mosh. Metod bitta, lekin har obyekt o'z ma'lumoti bilan ishlaydi. self ning vazifasi aynan shu.
Boshlang'ich qiymatli atribut
Ba'zi atributlar tashqaridan berilmaydi, obyekt yaratilganda boshlang'ich qiymat oladi:
class Mashina: def __init__(self, marka, model, yil): self.marka = marka self.model = model self.yil = yil self.probeg = 0 def tavsif(self): return f"{self.yil} {self.marka} {self.model}".title() def probegni_oqi(self): print(f"Probeg: {self.probeg:,} km") mashina = Mashina("chevrolet", "cobalt", 2024) print(mashina.tavsif()) mashina.probegni_oqi()
2024 Chevrolet Cobalt Probeg: 0 km
Atributni o'zgartirish: to'g'ridan-to'g'ri yoki metod orqali
Atributni to'g'ridan-to'g'ri o'zgartirish mumkin:
mashina.probeg = 23_500 mashina.probegni_oqi()
Probeg: 23,500 km
Lekin bu xavfli: hech kim probegni orqaga qaytarmasligi kerak. Shuning uchun o'zgartirishni tekshiruvli metod orqali qilamiz:
class Mashina: def __init__(self, marka, model, yil): self.marka = marka self.model = model self.yil = yil self.probeg = 0 def tavsif(self): return f"{self.yil} {self.marka} {self.model}".title() def probegni_oqi(self): print(f"Probeg: {self.probeg:,} km") def probegni_yangila(self, km): if km >= self.probeg: self.probeg = km else: print("Probegni orqaga qaytarib bo'lmaydi!") def probegni_oshir(self, km): if km < 0: print("Manfiy masofa bo'lmaydi!") return self.probeg += km eski = Mashina("daewoo", "nexia", 2015) eski.probegni_yangila(180_000) eski.probegni_oqi() eski.probegni_oshir(350) eski.probegni_oqi() eski.probegni_yangila(1_000) eski.probegni_oshir(-500) eski.probegni_oqi()
Probeg: 180,000 km Probeg: 180,350 km Probegni orqaga qaytarib bo'lmaydi! Manfiy masofa bo'lmaydi! Probeg: 180,350 km
Bu OOP ning asosiy g'oyalaridan biri — inkapsulyatsiya: obyekt o'z ma'lumotini o'zi qo'riqlaydi. 18-bobda buni @property bilan yanada yaxshi qilamiz.
Misol: bank hisobi
class BankHisobi: def __init__(self, egasi, balans=0): self.egasi = egasi self.balans = balans self.tarix = [] def kirim(self, summa): self.balans += summa self.tarix.append(f"+{summa:,}") def chiqim(self, summa): if summa > self.balans: print(f"{self.egasi}: mablag' yetarli emas (balans {self.balans:,})") return False self.balans -= summa self.tarix.append(f"-{summa:,}") return True def hisobot(self): print(f"{self.egasi}: {self.balans:,} so'm | {', '.join(self.tarix)}") ali = BankHisobi("Ali", 100_000) ali.kirim(50_000) ali.chiqim(30_000) ali.chiqim(500_000) ali.hisobot() vali = BankHisobi("Vali") vali.kirim(10_000) vali.hisobot()
Ali: mablag' yetarli emas (balans 120,000) Ali: 120,000 so'm | +50,000, -30,000 Vali: 10,000 so'm | +10,000
Ikki obyektning tarix ro'yxatlari alohida: har biri __init__ da o'zining yangi ro'yxatini oldi.
Klass atributi
self. bilan yozilgan atribut — har bir obyektniki. Klassning o'ziga yozilgan atribut — hammaga umumiy:
class Talaba: universitet = "TATU" soni = 0 def __init__(self, ism): self.ism = ism Talaba.soni += 1 a = Talaba("Ali") b = Talaba("Sarvinoz") print(a.universitet, b.universitet) print("Jami talabalar:", Talaba.soni)
TATU TATU Jami talabalar: 2
OOP dagi to'rtta keng tarqalgan xato
>
self ni unutishclass It: def __init__(self, ism): self.ism = ism def hura(): print("Vov!") It("Rex").hura()
TypeError: It.hura() takes 0 positional arguments but 1 was given
Python metodga obyektni doim birinchi argument qilib beradi. hura() hech narsa kutmagani uchun "0 ta kutgan edim, 1 ta keldi" deydi.
>
self. siz murojaatclass It: def __init__(self, ism): self.ism = ism def tanishtir(self): print(f"Men {ism}man") It("Rex").tanishtir()
NameError: name 'ism' is not defined
ism — __init__ ning lokal parametri edi, u allaqachon yo'q. Obyektning atributi — self.ism.
>
__init__ ni noto'g'ri yozishclass It: def _init_(self, ism): self.ism = ism rex = It("Rex")
TypeError: It() takes no arguments
Bitta pastki chiziq bilan yozilgan _init_ — oddiy metod, konstruktor emas. Python argument kutmaydigan standart konstruktorni ishlatdi va "Rex" ni qayerga qo'yishni bilmadi. To'g'risi: __init__ — ikki tomonda ikkitadan.
>
class It: def __init__(self, ism="Rex"): self.ism = ism a = It b = It() print(a) print(b.ism)
<class '__main__.It'> Rex
a = It obyekt yasamadi — a endi klassning o'zi. 13-bobdagi "qavssiz funksiya" xatosi bilan bir xil.
Kitoblarda
- Python asoslari: OOP tushunchalari 95–97-betlar, sinf va obyektlar 98–101-betlar, konstruktor 102–105-betlar.
- Python Crash Course: 9-bob Classes 157–167-betlar (Creating the Dog Class 158-bet, Working with Classes and Instances 162-bet, Modifying Attribute Values 164-bet).
Xulosa
class Nom:— chizma;Nom(...)— obyekt.__init__(self, ...)— obyekt yasalganda o'zi ishlaydi; atributlarself.nom = qiymat.- Har bir metodning birinchi parametri —
self; atributgaself.nomorqali murojaat. - Atributni tekshiruvli metod orqali o'zgartiring (inkapsulyatsiya).
self.x— har obyektniki, klassdagix— umumiy.
Mashqlar
Avval klassni yozing, keyin input() dan qiymat olib, obyekt yasang va natijani chiqaring.
Tortburchak klassini yozing: __init__(self, a, b), yuza() va perimetr() metodlari bilan. Tomonlar berilgan; avval yuzani, keyin perimetrni chiqaring.
| Kirish | Kutilgan natija |
|---|---|
| 3, 4 | 12 14 |
| 2.5, 2 | 5 9 |
| 1, 1 | 1 4 |
Yechimni ko'rish
class Tortburchak: def __init__(self, a, b): self.a = a self.b = b def yuza(self): return self.a * self.b def perimetr(self): return 2 * (self.a + self.b) t = Tortburchak(float(input()), float(input())) print(t.yuza(), t.perimetr())
Nuqta klassini yozing: x, y atributlari va masofa(boshqa) metodi — boshqa nuqtagacha masofani qaytaradi. Ikki nuqta ikki qatorda x y ko'rinishida berilgan; masofani chiqaring.
| Kirish | Kutilgan natija |
|---|---|
| 0 0, 3 4 | 5 |
| 1 2, 4 6 | 5 |
| 2 2, 2 2 | 0 |
Yechimni ko'rish
class Nuqta: def __init__(self, x, y): self.x = x self.y = y def masofa(self, boshqa): return ((self.x - boshqa.x) ** 2 + (self.y - boshqa.y) ** 2) ** 0.5 a = Nuqta(*[float(s) for s in input().split()]) b = Nuqta(*[float(s) for s in input().split()]) print(a.masofa(b))
BankHisobi klassini yozing: balans 0 dan boshlanadi; kirim(summa); chiqim(summa) — mablag' yetmasa, balans o'zgarmaydi. Birinchi qatorda amallar soni N, keyin N qatorda + summa yoki - summa. Oxirgi balansni chiqaring.
| Kirish | Kutilgan natija |
|---|---|
| 3, + 100, - 30, - 500 | 70 |
| 2, - 10, + 5 | 5 |
| 1, + 0 | 0 |
Yechimni ko'rish
class BankHisobi: def __init__(self): self.balans = 0 def kirim(self, summa): self.balans += summa def chiqim(self, summa): if summa <= self.balans: self.balans -= summa h = BankHisobi() for _ in range(int(input())): belgi, summa = input().split() if belgi == "+": h.kirim(int(summa)) else: h.chiqim(int(summa)) print(h.balans)
Talaba klassini yozing: ism, baholar (bo'sh ro'yxat), baho_qosh(b) va ortacha() metodlari (baho yo'q bo'lsa — 0). Birinchi qatorda ism, ikkinchisida baholar. ism: o'rtacha ko'rinishida, o'rtachani 2 xona bilan chiqaring.
| Kirish | Kutilgan natija |
|---|---|
| Sarvinoz, 5 4 5 | Sarvinoz: 4.67 |
| Ali, 3 | Ali: 3.00 |
Yechimni ko'rish
class Talaba: def __init__(self, ism): self.ism = ism self.baholar = [] def baho_qosh(self, b): self.baholar.append(b) def ortacha(self): return sum(self.baholar) / len(self.baholar) if self.baholar else 0 t = Talaba(input()) for s in input().split(): t.baho_qosh(int(s)) print(f"{t.ism}: {t.ortacha():.2f}")
Hisoblagich klassini yozing: qiymat 0 dan boshlanadi; oshir(), kamaytir() (0 dan pastga tushmaydi), nolga() metodlari. Bitta qatorda buyruqlar berilgan: +, -, 0. Hammasini bajarib, oxirgi qiymatni chiqaring.
| Kirish | Kutilgan natija |
|---|---|
| + + + - | 2 |
| - - + | 1 |
| + + 0 + | 1 |
Yechimni ko'rish
class Hisoblagich: def __init__(self): self.qiymat = 0 def oshir(self): self.qiymat += 1 def kamaytir(self): if self.qiymat > 0: self.qiymat -= 1 def nolga(self): self.qiymat = 0 h = Hisoblagich() for b in input().split(): if b == "+": h.oshir() elif b == "-": h.kamaytir() else: h.nolga() print(h.qiymat)
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.