Asosiy qismga o'tish

Klass va obyekt (OOP asoslari)

16-bob 17 kod bloki 2274 so'z

Bu bobda

  • klass va obyekt nima ekanini
  • __init__ va self ni 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:

python6 qator
talaba = {"ism": "Sarvinoz", "baholar": [5, 4, 5]}

def ortacha(t):
    return sum(t["baholar"]) / len(t["baholar"])

print(ortacha(talaba))
Natija
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

python16 qator
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()
Natija
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 obyektning ism atributiga berilgan qiymatni yoz".
  • otir va dumalash — metodlar: klass ichidagi funksiyalar. Birinchi parametri doim self.
  • It("Rex", 3) — obyekt yasash. self ni biz bermaymiz, Python o'zi qo'yadi: "Rex" → ism, 3 → yosh.

Bir klass — ko'p obyekt

Har bir obyekt o'z atributlariga ega:

python14 qator
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)
Natija
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:

python17 qator
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()
Natija
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:

python2 qator
mashina.probeg = 23_500
mashina.probegni_oqi()
Natija
Probeg: 23,500 km

Lekin bu xavfli: hech kim probegni orqaga qaytarmasligi kerak. Shuning uchun o'zgartirishni tekshiruvli metod orqali qilamiz:

python34 qator
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()
Natija
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

python31 qator
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()
Natija
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:

python13 qator
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)
Natija
TATU TATU
Jami talabalar: 2

OOP dagi to'rtta keng tarqalgan xato

>

  • Metodda self ni unutish
  • <

    python9 qator
    class It:
        def __init__(self, ism):
            self.ism = ism
    
        def hura():
            print("Vov!")
    
    
    It("Rex").hura()
    
    Xato xabari
    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.

    >

  • Atributga self. siz murojaat
  • <

    python9 qator
    class It:
        def __init__(self, ism):
            self.ism = ism
    
        def tanishtir(self):
            print(f"Men {ism}man")
    
    
    It("Rex").tanishtir()
    
    Xato xabari
    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 yozish
  • <

    python6 qator
    class It:
        def _init_(self, ism):
            self.ism = ism
    
    
    rex = It("Rex")
    
    Xato xabari
    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.

    >

  • Klass nomini qavssiz ishlatish
  • <

    python9 qator
    class It:
        def __init__(self, ism="Rex"):
            self.ism = ism
    
    
    a = It
    b = It()
    print(a)
    print(b.ism)
    
    Natija
    <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; atributlar self.nom = qiymat.
    • Har bir metodning birinchi parametri — self; atributga self.nom orqali murojaat.
    • Atributni tekshiruvli metod orqali o'zgartiring (inkapsulyatsiya).
    • self.x — har obyektniki, klassdagi x — umumiy.

    Mashqlar

    Avval klassni yozing, keyin input() dan qiymat olib, obyekt yasang va natijani chiqaring.

    16.1

    Tortburchak klassini yozing: __init__(self, a, b), yuza() va perimetr() metodlari bilan. Tomonlar berilgan; avval yuzani, keyin perimetrni chiqaring.

    KirishKutilgan natija
    3, 412 14
    2.5, 25 9
    1, 11 4
    Yechimni ko'rish
    python14 qator
    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())
    
    16.2

    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.

    KirishKutilgan natija
    0 0, 3 45
    1 2, 4 65
    2 2, 2 20
    Yechimni ko'rish
    python12 qator
    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))
    
    16.3

    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.

    KirishKutilgan natija
    3, + 100, - 30, - 50070
    2, - 10, + 55
    1, + 00
    Yechimni ko'rish
    python20 qator
    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)
    
    16.4

    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.

    KirishKutilgan natija
    Sarvinoz, 5 4 5Sarvinoz: 4.67
    Ali, 3Ali: 3.00
    Yechimni ko'rish
    python16 qator
    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}")
    
    16.5

    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.

    KirishKutilgan natija
    + + + -2
    - - +1
    + + 0 +1
    Yechimni ko'rish
    python24 qator
    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.

    Telegramda yozish Narxlar