15-bo‘lim
OOP asoslari - klass va obyekt
Obyektga yo'naltirilgan dasturlashga kirish: klass yaratish, __init__ konstruktori, atributlar, metodlar va self nima ekanligi.
Ushbu bo‘lim mundarijasi
Shu paytgacha biz ma'lumot va uni qayta ishlaydigan funksiyalarni alohida saqladik. Obyektga yo'naltirilgan dasturlash (OOP) ularni bitta joyga birlashtiradi.
Muammo: ma'lumot tarqoq #
# Uchta talaba - oltita o'zgaruvchi
talaba1_ism = "Husanboy"
talaba1_baholar = [85, 92]
talaba2_ism = "Sardor"
talaba2_baholar = [78, 80]
def ortacha(baholar):
return sum(baholar) / len(baholar)
print(f"{talaba1_ism}: {ortacha(talaba1_baholar)}")
Talabalar soni oshgani sari bu yondashuv chidab bo'lmas holga keladi. Yechim - klass yaratish.
Klass va obyekt #
Klass - uy loyihasi (chizma). Unda xonalar soni, eshiklar joyi ko'rsatilgan. Obyekt - shu loyiha bo'yicha qurilgan aniq uy. Bitta loyihadan yuzta uy qurish mumkin va har birining o'z rangi, egasi bo'ladi.
Birinchi klass #
class Talaba:
"""Talaba haqidagi ma'lumotni saqlaydigan klass."""
def __init__(self, ism, yosh, shahar):
"""Yangi talaba obyektini yaratadi."""
self.ism = ism
self.yosh = yosh
self.shahar = shahar
self.baholar = []
# Obyekt yaratish
birinchi = Talaba("Husanboy Qodirov", 25, "Namangan")
ikkinchi = Talaba("Sardor Aliyev", 25, "Toshkent")
print(birinchi.ism)
print(ikkinchi.shahar)
print(birinchi.baholar)
Husanboy Qodirov
Toshkent
[]
__init__ va self #
| Element | Ma'nosi |
|---|---|
class Talaba: | Yangi klass e'lon qilinadi (PascalCase) |
__init__ | Konstruktor - obyekt yaratilganda avtomatik chaqiriladi |
self | Yaratilayotgan obyektning o'ziga havola |
self.ism = ism | Obyektga atribut biriktiriladi |
self nima?self - bu "shu obyektning o'zi". Python uni avtomatik uzatadi:
birinchi.baholar # aslida Talaba.baholar(birinchi) kabi ishlaydi
Har bir metodning birinchi parametri self bo'lishi kerak. Uni yozishni unutish - eng ko'p uchraydigan xatolardan biri.
Metodlar #
Metod - klass ichidagi funksiya.
class Talaba:
"""Talaba ma'lumotlari va baholari bilan ishlaydi."""
def __init__(self, ism, yosh, shahar):
self.ism = ism
self.yosh = yosh
self.shahar = shahar
self.baholar = []
def baho_qosh(self, baho):
"""Yangi baho qo'shadi."""
if 0 <= baho <= 100:
self.baholar.append(baho)
else:
raise ValueError("Baho 0 va 100 orasida bo'lishi kerak")
def ortacha(self):
"""O'rtacha bahoni qaytaradi."""
if not self.baholar:
return 0.0
return sum(self.baholar) / len(self.baholar)
def harfli_baho(self):
"""O'rtachani harfli bahoga aylantiradi."""
ball = self.ortacha()
if ball >= 90:
return "A"
if ball >= 80:
return "B"
if ball >= 70:
return "C"
return "F"
def hisobot(self):
"""Talaba haqida qisqacha hisobot chiqaradi."""
print(f"{self.ism} ({self.yosh} yosh, {self.shahar})")
print(f" Baholar: {self.baholar}")
print(f" O'rtacha: {self.ortacha():.1f}")
print(f" Baho: {self.harfli_baho()}")
talaba = Talaba("Husanboy Qodirov", 25, "Namangan")
talaba.baho_qosh(85)
talaba.baho_qosh(92)
talaba.baho_qosh(78)
talaba.hisobot()
Husanboy Qodirov (25 yosh, Namangan)
Baholar: [85, 92, 78]
O'rtacha: 85.0
Baho: B
Klass atributlari #
Obyekt atributi har bir obyektga xos, klass atributi esa hammaga umumiy:
class Talaba:
# Klass atributi - barcha obyektlar uchun bitta
universitet = "Toshkent Axborot Texnologiyalari Universiteti"
talabalar_soni = 0
def __init__(self, ism):
self.ism = ism # obyekt atributi
Talaba.talabalar_soni += 1
birinchi = Talaba("Husanboy")
ikkinchi = Talaba("Sardor")
uchinchi = Talaba("Malika")
print(birinchi.universitet)
print(ikkinchi.universitet)
print(f"Jami talabalar: {Talaba.talabalar_soni}")
Toshkent Axborot Texnologiyalari Universiteti
Toshkent Axborot Texnologiyalari Universiteti
Jami talabalar: 3
Maxsus metodlar (dunder) #
Ikki tomondan pastki chiziq bilan yoziladigan metodlar Python'ga obyekt bilan qanday ishlashni o'rgatadi.
class Mahsulot:
def __init__(self, nomi, narxi, soni=1):
self.nomi = nomi
self.narxi = narxi
self.soni = soni
def __str__(self):
"""print() chaqirilganda ko'rinadigan matn."""
return f"{self.nomi} x{self.soni} - {self.narxi * self.soni:,} so'm"
def __repr__(self):
"""Nosozlikni tuzatishda ko'rinadigan matn."""
return f"Mahsulot('{self.nomi}', {self.narxi}, {self.soni})"
def __len__(self):
"""len() chaqirilganda."""
return self.soni
def __eq__(self, boshqa):
"""== operatori uchun."""
return self.nomi == boshqa.nomi and self.narxi == boshqa.narxi
def __lt__(self, boshqa):
"""< operatori uchun (saralashda kerak)."""
return self.narxi < boshqa.narxi
klaviatura = Mahsulot("Klaviatura", 185_000, 2)
sichqoncha = Mahsulot("Sichqoncha", 95_000)
print(klaviatura) # __str__
print(repr(sichqoncha)) # __repr__
print(len(klaviatura)) # __len__
print(klaviatura == sichqoncha) # __eq__
print(sichqoncha < klaviatura) # __lt__
savat = [klaviatura, sichqoncha, Mahsulot("Monitor", 2_450_000)]
for mahsulot in sorted(savat):
print(" ", mahsulot)
Klaviatura x2 - 370,000 so'm
Mahsulot('Sichqoncha', 95000, 1)
2
False
True
Sichqoncha x1 - 95,000 so'm
Klaviatura x2 - 370,000 so'm
Monitor x1 - 2,450,000 so'm
| Metod | Qachon chaqiriladi |
|---|---|
__init__ | Obyekt yaratilganda |
__str__ | print(obyekt), str(obyekt) |
__repr__ | REPL'da, repr(obyekt) |
__len__ | len(obyekt) |
__eq__ | obyekt1 == obyekt2 |
__lt__, __gt__ | <, > va saralash |
__add__ | obyekt1 + obyekt2 |
__contains__ | x in obyekt |
__getitem__ | obyekt[i] |
__str__ ni har doim yozing__str__ bo'lmasa print(obyekt) shunday narsa chiqaradi:
<__main__.Mahsulot object at 0x000001F8A2B3C4D0> - bu hech kimga foyda bermaydi.
@property - hisoblanadigan atribut #
class Aylana:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
"""Radiusni qaytaradi."""
return self._radius
@radius.setter
def radius(self, qiymat):
"""Radiusni tekshirib o'rnatadi."""
if qiymat <= 0:
raise ValueError("Radius musbat bo'lishi kerak")
self._radius = qiymat
@property
def yuza(self):
"""Yuzani hisoblab qaytaradi (metod emas, atribut kabi ishlatiladi)."""
return 3.14159 * self._radius ** 2
@property
def uzunlik(self):
return 2 * 3.14159 * self._radius
aylana = Aylana(5)
print(f"Radius: {aylana.radius}")
print(f"Yuza: {aylana.yuza:.2f}") # qavssiz!
print(f"Uzunlik: {aylana.uzunlik:.2f}")
aylana.radius = 10
print(f"Yangi yuza: {aylana.yuza:.2f}")
try:
aylana.radius = -3
except ValueError as xato:
print(f"Xato: {xato}")
Radius: 5
Yuza: 78.54
Uzunlik: 31.42
Yangi yuza: 314.16
Xato: Radius musbat bo'lishi kerak
Amaliy misol: bank hisobi #
# ============================================
# Bank hisobi klassi
# ============================================
from datetime import datetime
class BankHisobi:
"""Oddiy bank hisobi: to'ldirish, yechish va tarix."""
bank_nomi = "Softromeda Bank"
minimal_qoldiq = 10_000
def __init__(self, egasi, boshlangich_balans=0):
self.egasi = egasi
self._balans = boshlangich_balans
self.tarix = []
self.ochilgan_sana = datetime.now()
@property
def balans(self):
"""Balansni faqat o'qish uchun ochamiz."""
return self._balans
def toldirish(self, summa):
if summa <= 0:
raise ValueError("Summa musbat bo'lishi kerak")
self._balans += summa
self._qayd("To'ldirish", summa)
return self._balans
def yechish(self, summa):
if summa <= 0:
raise ValueError("Summa musbat bo'lishi kerak")
if self._balans - summa < self.minimal_qoldiq:
raise ValueError(
f"Mablag' yetarli emas. Minimal qoldiq: {self.minimal_qoldiq:,} so'm"
)
self._balans -= summa
self._qayd("Yechish", summa)
return self._balans
def _qayd(self, turi, summa):
"""Ichki metod - amalni tarixga yozadi."""
self.tarix.append({
"turi": turi,
"summa": summa,
"balans": self._balans,
"vaqt": datetime.now().strftime("%H:%M:%S"),
})
def kochirma(self):
"""Hisob ko'chirmasini chiqaradi."""
print("=" * 50)
print(f"{self.bank_nomi:^50}")
print(f"{'Hisob egasi: ' + self.egasi:^50}")
print("=" * 50)
print(f"{'Vaqt':<12}{'Amal':<16}{'Summa':>10}{'Balans':>12}")
print("-" * 50)
for amal in self.tarix:
belgi = "+" if amal["turi"] == "To'ldirish" else "-"
print(f"{amal['vaqt']:<12}{amal['turi']:<16}"
f"{belgi + format(amal['summa'], ','):>10}"
f"{amal['balans']:>12,}")
print("=" * 50)
print(f"{'Joriy balans:':<38}{self._balans:>12,}")
def __str__(self):
return f"{self.egasi}: {self._balans:,} so'm"
hisob = BankHisobi("Husanboy Qodirov", 500_000)
hisob.toldirish(250_000)
hisob.yechish(100_000)
hisob.toldirish(75_000)
hisob.kochirma()
print()
try:
hisob.yechish(10_000_000)
except ValueError as xato:
print(f"Amal rad etildi: {xato}")
print(hisob)
==================================================
Softromeda Bank
Hisob egasi: Husanboy Qodirov
==================================================
Vaqt Amal Summa Balans
--------------------------------------------------
14:52:10 To'ldirish +250,000 750,000
14:52:10 Yechish -100,000 650,000
14:52:10 To'ldirish +75,000 725,000
==================================================
Joriy balans: 725,000
Amal rad etildi: Mablag' yetarli emas. Minimal qoldiq: 10,000 so'm
Husanboy Qodirov: 725,000 so'm
Kitob klassini yarating:
- Atributlar:
nomi,muallif,yil,sahifalar,oqilgan_sahifa. oqish(sahifalar_soni)metodi - o'qilgan sahifani oshirsin (kitob oxiridan oshib ketmasin).@property foiz- necha foiz o'qilganini qaytarsin.__str__metodi -"Nomi (muallif, yil) - 45% o'qilgan"ko'rinishida qaytarsin.- Uchta kitob obyekti yaratib, ularni
foizbo'yicha saralang.
Xulosa #
- Klass - chizma, obyekt - shu chizma bo'yicha yaratilgan nusxa.
__init__konstruktor bo'lib, obyekt yaratilganda avtomatik ishlaydi.selfhar bir metodning birinchi parametri - obyektning o'ziga havola.- Klass atributi barcha obyektlarga umumiy, obyekt atributi har biriga xos.
__str__,__eq__,__lt__kabi dunder metodlar obyektni Python bilan integratsiya qiladi.@propertymetodni atribut kabi ishlatish imkonini beradi.
Keyingi bo'limda OOP ning uchta asosiy tamoyilini - meros, inkapsulyatsiya va polimorfizmni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.