Maxsus metodlar, @property va dataclass
Bu bobda
- obyektni chiroyli chiqarishni:
__str__va__repr__ - obyektlarni solishtirish va tartiblashni:
__eq__,__lt__ - o'z klassingizga
+valen()ni o'rgatishni - atributni
@propertybilan qo'riqlashni @classmethod,@staticmethodva@dataclassni
Muammo: print(obyekt) xunuk chiqadi
class Kitob: def __init__(self, nom, muallif, yil): self.nom = nom self.muallif = muallif self.yil = yil k = Kitob("O'tkan kunlar", "Abdulla Qodiriy", 1926) print(k)
<__main__.Kitob object at 0x7fb0d0742b60>
Python obyekt haqida faqat klass nomi va xotiradagi manzilni biladi. Uni qanday ko'rsatishni o'zimiz aytishimiz kerak.
__str__ va __repr__
Ikki pastki chiziq bilan o'ralgan metodlar (__init__ kabi) — maxsus metodlar (dunder methods). Python ularni ma'lum holatlarda o'zi chaqiradi.
class Kitob: def __init__(self, nom, muallif, yil): self.nom = nom self.muallif = muallif self.yil = yil def __str__(self): return f"«{self.nom}» — {self.muallif}, {self.yil}" def __repr__(self): return f"Kitob({self.nom!r}, {self.muallif!r}, {self.yil})" k = Kitob("O'tkan kunlar", "Abdulla Qodiriy", 1926) print(k) print(str(k)) print([k]) print(repr(k))
«O'tkan kunlar» — Abdulla Qodiriy, 1926
«O'tkan kunlar» — Abdulla Qodiriy, 1926
[Kitob("O'tkan kunlar", 'Abdulla Qodiriy', 1926)]
Kitob("O'tkan kunlar", 'Abdulla Qodiriy', 1926)__str__— o'quvchi uchun:print()vastr()ishlatadi.__repr__— dasturchi uchun: ro'yxat ichida, Jupyterda katak oxirida ko'rinadi. Yaxshi__repr__obyektni qayta yasash mumkin bo'lgan kodga o'xshaydi.
{self.nom!r} — f-string ichida qiymatning repr() ini qo'yadi (satr qo'shtirnoq bilan chiqadi).
__eq__ va __lt__: solishtirish
Odatda ikki obyekt faqat o'sha bitta obyekt bo'lsagina teng:
class Pul: def __init__(self, som): self.som = som print(Pul(1000) == Pul(1000))
False
Ma'no bo'yicha solishtirish uchun __eq__ (==) va __lt__ (<) yoziladi:
class Pul: def __init__(self, som): self.som = som def __eq__(self, boshqa): return self.som == boshqa.som def __lt__(self, boshqa): return self.som < boshqa.som def __repr__(self): return f"Pul({self.som})" print(Pul(1000) == Pul(1000)) print(Pul(500) < Pul(1000)) narxlar = [Pul(25_000), Pul(4_000), Pul(12_500)] print(sorted(narxlar)) print(max(narxlar))
True True [Pul(4000), Pul(12500), Pul(25000)] Pul(25000)
__lt__ yozilgani uchun sorted(), max(), min() ham ishladi — ular ichkarida < ni ishlatadi.
__add__ va __len__: o'z operatorlaringiz
a + b yozilganda Python aslida a.__add__(b) ni chaqiradi. Shuni yozsak, klassimiz + ni tushunadi:
class Vektor: def __init__(self, x, y): self.x = x self.y = y def __add__(self, boshqa): return Vektor(self.x + boshqa.x, self.y + boshqa.y) def __mul__(self, son): return Vektor(self.x * son, self.y * son) def __abs__(self): return (self.x ** 2 + self.y ** 2) ** 0.5 def __repr__(self): return f"Vektor({self.x}, {self.y})" a = Vektor(1, 2) b = Vektor(3, 4) print(a + b) print(a * 3) print(abs(b))
Vektor(4, 6) Vektor(3, 6) 5.0
__len__ — len() uchun:
class Savat: def __init__(self): self.mahsulotlar = [] def qosh(self, nom): self.mahsulotlar.append(nom) def __len__(self): return len(self.mahsulotlar) def __contains__(self, nom): return nom in self.mahsulotlar s = Savat() s.qosh("non") s.qosh("sut") print(len(s)) print("sut" in s, "go'sht" in s)
2 True False
| Maxsus metod | Qachon chaqiriladi |
|---|---|
__init__ |
obyekt yasalganda |
__str__ |
print(x), str(x) |
__repr__ |
Jupyter, ro'yxat ichida, repr(x) |
__eq__ |
x == y |
__lt__ |
x < y, sorted(), min(), max() |
__add__ |
x + y |
__len__ |
len(x) |
__contains__ |
y in x |
@property: qo'riqlanadigan atribut
16-bobda probegni metod orqali tekshirdik. Lekin baribir mashina.probeg = -5 deb yozish mumkin edi. @property atributni tashqaridan oddiy atributdek ko'rsatadi, lekin ichkarida tekshiruv qiladi:
class Talaba: def __init__(self, ism, yosh): self.ism = ism self.yosh = yosh @property def yosh(self): return self._yosh @yosh.setter def yosh(self, qiymat): if not 0 < qiymat < 120: raise ValueError(f"Yosh noto'g'ri: {qiymat}") self._yosh = qiymat t = Talaba("Ali", 20) print(t.yosh) t.yosh = 21 print(t.yosh) t.yosh = -5
20 21
ValueError: Yosh noto'g'ri: -5
@propertyostidagiyosh(self)— o'qish:t.yoshyozilganda chaqiriladi.@yosh.setterostidagiyosh(self, qiymat)— yozish:t.yosh = ...da chaqiriladi.- Haqiqiy qiymat
self._yoshda saqlanadi. Boshidagi_— "bu ichki narsa, tashqaridan tegmang" degan kelishuv. raise ValueError(...)— xato yuzaga keltirish; uni 20-bobda batafsil ko'ramiz.
__init__ dagi self.yosh = yosh ham setter orqali o'tadi, shuning uchun Talaba("Ali", -5) ham darhol rad etiladi.
Setter yozilmasa — atribut faqat o'qiladigan bo'ladi. Hisoblanadigan qiymatlar uchun qulay:
class Tortburchak: def __init__(self, a, b): self.a = a self.b = b @property def yuza(self): return self.a * self.b t = Tortburchak(3, 4) print(t.yuza) t.a = 10 print(t.yuza)
12 40
t.yuza — qavssiz, xuddi atributdek; lekin har safar yangidan hisoblanadi.
@classmethod va @staticmethod
@classmethod— obyekt emas, klassning o'zini (cls) oladi. Ko'pincha "boshqa usulda obyekt yasash" uchun ishlatiladi.@staticmethod— na obyektni, na klassni oladi; klassga mantiqan tegishli oddiy funksiya.
class Sana: def __init__(self, kun, oy, yil): self.kun = kun self.oy = oy self.yil = yil @classmethod def matndan(cls, matn): kun, oy, yil = matn.split(".") return cls(int(kun), int(oy), int(yil)) @staticmethod def kabisami(yil): return (yil % 4 == 0 and yil % 100 != 0) or yil % 400 == 0 def __str__(self): return f"{self.kun:02d}.{self.oy:02d}.{self.yil}" s = Sana.matndan("14.10.2026") print(s) print(Sana.kabisami(2024), Sana.kabisami(2026))
14.10.2026 True False
@dataclass: kamroq yozib, ko'proq olish
Ko'p klasslar asosan ma'lumot saqlaydi: __init__, __repr__, __eq__ — hammasi bir xil andoza. dataclass ularni avtomatik yozib beradi:
from dataclasses import dataclass, field @dataclass class Mahsulot: nom: str narx: int soni: int = 1 teglar: list = field(default_factory=list) def jami(self): return self.narx * self.soni a = Mahsulot("non", 4000, 3) b = Mahsulot("non", 4000, 3) print(a) print(a == b) print(a.jami())
Mahsulot(nom='non', narx=4000, soni=3, teglar=[]) True 12000
nom: str— atribut va uning turi (type hint). Python turni tekshirmaydi, bu o'quvchi va muharrir uchun izoh.soni: int = 1— standart qiymat.field(default_factory=list)— har bir obyektga yangi ro'yxat (14-bobdagi[]tuzog'idan himoya).__init__,__repr__,__eq__avtomatik yozildi.
@dataclass(order=True) — <, sorted() ham ishlaydi (maydonlar tartibi bo'yicha solishtiradi).
Kitoblarda
- Python asoslari: OOP bo'limi 95–112-betlar (maxsus metodlar va dataclass bu kitobda yo'q).
- Python Crash Course: 9-bob, Importing Classes 173–178-betlar, The Python Standard Library 179-bet. Maxsus metodlar va
@propertykitobda o'rgatilmaydi — bu bob ikkala kitobni ham to'ldiradi.
Xulosa
__str__—printuchun,__repr__— dasturchi uchun.__eq__,__lt__— solishtirish va tartiblash;__add__,__len__,__contains__—+,len(),in.@property+@nom.setter— tekshiruvli atribut;_nom— ichki atribut kelishuvi.@classmethod— klassni oladi (cls), muqobil konstruktor uchun;@staticmethod— oddiy funksiya klass ichida.@dataclass— ma'lumot klasslari uchun__init__,__repr__,__eq__ni avtomatik yozadi.
Mashqlar
Kasr(surat, maxraj) klassini yozing: konstruktor kasrni qisqartirib saqlaydi (math.gcd), __add__ ikki kasrni qo'shadi, __str__ uni surat/maxraj ko'rinishida qaytaradi. Ikki qatorda ikki kasr a/b ko'rinishida berilgan; yig'indisini chiqaring.
| Kirish | Kutilgan natija |
|---|---|
| 1/2, 1/3 | 5/6 |
| 1/4, 1/4 | 1/2 |
| 2/3, 1/3 | 1/1 |
Yechimni ko'rish
import math class Kasr: def __init__(self, surat, maxraj): e = math.gcd(surat, maxraj) self.surat = surat // e self.maxraj = maxraj // e def __add__(self, b): return Kasr(self.surat * b.maxraj + b.surat * self.maxraj, self.maxraj * b.maxraj) def __str__(self): return f"{self.surat}/{self.maxraj}" def oqi(): s, m = input().split("/") return Kasr(int(s), int(m)) print(oqi() + oqi())
Vektor(x, y) klassini __add__, __sub__, __abs__ (uzunlik) va __str__ ((x, y) ko'rinishida) bilan yozing. Ikki vektor ikki qatorda berilgan; ularning yig'indisini, ayirmasini va yig'indi uzunligini alohida qatorlarda chiqaring.
| Kirish | Kutilgan natija |
|---|---|
| 1 2, 3 4 | (4, 6) (-2, -2) 7.211102550927978 |
| 3 0, 0 4 | (3, 4) (3, -4) 5.0 |
Yechimni ko'rish
class Vektor: def __init__(self, x, y): self.x, self.y = x, y def __add__(self, b): return Vektor(self.x + b.x, self.y + b.y) def __sub__(self, b): return Vektor(self.x - b.x, self.y - b.y) def __abs__(self): return (self.x ** 2 + self.y ** 2) ** 0.5 def __str__(self): return f"({self.x}, {self.y})" a = Vektor(*[int(s) for s in input().split()]) b = Vektor(*[int(s) for s in input().split()]) print(a + b) print(a - b) print(abs(a + b))
Harorat klassini yozing: selsiy — @property, setter −273.15 dan past qiymatni rad etadi (ValueError); farengeyt — faqat o'qiladigan @property: C · 9/5 + 32. Selsiy berilgan; Farengeytni chiqaring. Qiymat imkonsiz bo'lsa — Xato. Xatoni ushlash uchun shu andozani ishlating (20-bobda batafsil): try: ichida obyekt yasab natijani chiqaring, except ValueError: ichida print("Xato").
| Kirish | Kutilgan natija |
|---|---|
| 100 | 212 |
| -40 | -40 |
| -300 | Xato |
Yechimni ko'rish
class Harorat: def __init__(self, selsiy): self.selsiy = selsiy @property def selsiy(self): return self._selsiy @selsiy.setter def selsiy(self, q): if q < -273.15: raise ValueError("absolyut noldan past") self._selsiy = q @property def farengeyt(self): return self._selsiy * 9 / 5 + 32 try: print(Harorat(float(input())).farengeyt) except ValueError: print("Xato")
@dataclass bilan Talaba(ism: str, ball: int) yozing va uni ball bo'yicha tartiblanadigan qiling (order=True uchun maydonlar tartibiga e'tibor bering yoki sorted(key=...) ishlating). Birinchi qatorda N, keyin N qatorda ism ball. Eng yuqori ball olgan talabaning ismini chiqaring.
| Kirish | Kutilgan natija |
|---|---|
| 3, Ali 78, Sarvinoz 91, Otabek 85 | Sarvinoz |
| 1, Vali 50 | Vali |
Yechimni ko'rish
from dataclasses import dataclass @dataclass class Talaba: ism: str ball: int talabalar = [] for _ in range(int(input())): ism, ball = input().split() talabalar.append(Talaba(ism, int(ball))) print(max(talabalar, key=lambda t: t.ball).ism)
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.