Mundarija (21)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Paradigma nima
- 2.2. OOP ning to'rt ustuni
- 2.3. Pythonda hamma narsa obyekt
- 2.4. Sinf va obyekt
- 2.5. Nega OOP paydo bo'lgan
- 2.6. Qachon OOP kerak — va qachon kerak emas
- 2.7. OOP tanqidi
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Bir muammo, to'rt yondashuv
- Misol 2 — Hamma narsa obyekt
- Misol 3 — Qachon sinf kerak emas
- Misol 4 — To'rt ustunni ko'rish
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
8.1-dars: OOP nima va nega kerak
8-QISM — OBYEKTGA YO'NALTIRILGAN DASTURLASH · 1-dars
1. Kirish va motivatsiya
Bank hisobini funksiyalar bilan yozamiz:
def hisob_yarat(egasi, balans=0):
return {"egasi": egasi, "balans": balans, "tarix": []}
def qoshish(hisob, summa):
hisob["balans"] += summa
hisob["tarix"].append(("+", summa))
def yechish(hisob, summa):
hisob["balans"] -= summa
hisob["tarix"].append(("-", summa))Ishlaydi. Lekin:
h = hisob_yarat("Aziz", 100)
yechish(h, 1000)
h["balans"] # -900 ⚠️ manfiy balans!
h["balans"] = 999999 # ⚠️ hech kim to'smaydi
h["blans"] = 50 # ⚠️ xato yozilgan kalit — xato yo'q
del h["tarix"] # ⚠️ tuzilma buzildi
qoshish({"a": 1}, 50) # ⚠️ KeyError, lekin faqat ish vaqtidaMuammolar:
- Ma'lumot va uni o'zgartiruvchi kod ajralgan — birga ushlab turadigan narsa yo'q
- Qoidalarni majburlash yo'q — balans manfiy bo'lishi mumkin
- Ichki tuzilma ochiq — har kim buzishi mumkin
- Turlar aralashib ketadi — lug'at lug'atdan farq qilmaydi
OOP shu to'rt muammoni hal qiladi:
class Hisob:
def __init__(self, egasi, balans=0):
self.egasi = egasi
self._balans = balans
self._tarix = []
def yechish(self, summa):
if summa > self._balans:
raise ValueError("Mablag' yetarli emas")
self._balans -= summa
self._tarix.append(("-", summa))Bu darsda:
- OOP nima — to'rt ustun
- Nega u paydo bo'lgan, qanday muammoni hal qiladi
- Pythonda hamma narsa obyekt
- Qachon OOP kerak, qachon kerak emas
- Boshqa paradigmalar bilan solishtirish
2. Nazariya — chuqur tushuntirish
2.1. Paradigma nima
Dasturlash paradigmasi — muammoni qanday bo'laklarga bo'lish haqidagi yondashuv.
| Paradigma | Asosiy birlik | Savol |
|---|---|---|
| Protsedura | Funksiya | "Qanday qadamlar bajariladi?" |
| Obyektga yo'naltirilgan | Obyekt | "Qanday narsalar bor va ular nima qiladi?" |
| Funksional | Sof funksiya | "Kirishdan chiqishga qanday almashtirish?" |
| Deklarativ | Tavsif | "Natija qanday ko'rinishi kerak?" |
Python — ko'p paradigmali til. U to'rttasini ham qo'llab-quvvatlaydi:
# Protsedura
natija = []
for x in sonlar:
if x > 0:
natija.append(x * 2)
# Funksional
natija = list(map(lambda x: x * 2, filter(lambda x: x > 0, sonlar)))
# Deklarativ (comprehension)
natija = [x * 2 for x in sonlar if x > 0]
# OOP
natija = Sonlar(sonlar).musbatlar().kopaytir(2).royxat()OOP — vosita, din emas. Har muammoga sinf yozish — xato.
2.2. OOP ning to'rt ustuni
1 Kapsulatsiya (encapsulation)
Ma'lumot va u bilan ishlaydigan kod bir joyda; ichki tafsilotlar yashiringan.
class Hisob:
def __init__(self, balans):
self._balans = balans # ichki
@property
def balans(self): # nazorat ostida o'qish
return self._balans
def qoshish(self, summa):
if summa <= 0:
raise ValueError("Musbat bo'lsin")
self._balans += summaFoyda: invariant (doim rost bo'ladigan qoida) saqlanadi. Bu yerda — balans faqat tekshirilgan usulda o'zgaradi.
2 Abstraksiya (abstraction)
Foydalanuvchi nima qilishini biladi, qanday qilishini emas.
fayl.read() # qanday o'qiydi — bizga farqi yo'q
royxat.sort() # Timsort? bizga farqi yo'q3 Meros (inheritance)
Yangi sinf mavjudining xatti-harakatini oladi va kengaytiradi.
class Hayvon:
def ovqatlanish(self): ...
class It(Hayvon): # It — Hayvon
def vovullash(self): ...4 Polimorfizm (polymorphism)
Bir xil interfeys — turli amalga oshirish.
for shakl in [Doira(5), Kvadrat(3), Uchburchak(3, 4, 5)]:
print(shakl.yuza()) # har biri o'zicha hisoblaydiPythonda polimorfizm merosni TALAB QILMAYDI — duck typing yetadi:
class Doira:
def yuza(self): return 3.14 * self.r ** 2
class Kvadrat: # meros yo'q
def yuza(self): return self.a ** 2
# Ikkalasi ham ishlaydi2.3. Pythonda hamma narsa obyekt
type(42) # <class 'int'>
type("a") # <class 'str'>
type([1]) # <class 'list'>
type(print) # <class 'builtin_function_or_method'>
type(int) # <class 'type'> ← sinf ham obyekt!
type(type) # <class 'type'> ← o'zi-o'zigaHar obyektning uch xususiyati bor:
| Xususiyat | Nima | Qanday olish |
|---|---|---|
| Identifikator | Xotiradagi joyi | id(x) |
| Tur | Qanday sinfdan | type(x) |
| Qiymat | Ma'lumoti | x |
x = 42
id(x), type(x), xShuning uchun:
(42).bit_length() # 6 — int ning metodi
"abc".upper() # 'ABC'
[].append # <built-in method append of list>
(5).__add__(3) # 8 — 5 + 3 aslida shuSiz OOP dan birinchi darsdan beri foydalanyapsiz — shunchaki bilmagansiz.
2.4. Sinf va obyekt
Sinf — chizma. Obyekt (nusxa) — chizmaga ko'ra qurilgan narsa.
Sinf: Uy Obyektlar
┌────────────────┐ ┌──────────────┐
│ xonalar: int │ ────► │ uy1: 3 xona │
│ rang: str │ ────► │ uy2: 5 xona │
│ │ ────► │ uy3: 2 xona │
│ bo'yash() │ └──────────────┘
└────────────────┘class Uy: # chizma
def __init__(self, xonalar):
self.xonalar = xonalar
uy1 = Uy(3) # nusxa
uy2 = Uy(5) # boshqa nusxa
uy1 is uy2 # False — alohida obyektlar
type(uy1) is type(uy2) # True — bir sinf2.5. Nega OOP paydo bo'lgan
Tarix:
| Yil | Voqea |
|---|---|
| 1962 | Simula 67 (Norvegiya) — birinchi sinf va obyekt |
| 1972 | Smalltalk (Alan Kay) — "obyekt" atamasi, xabar almashish |
| 1983 | C++ — OOP asosiy tillarga kirdi |
| 1995 | Java — "hamma narsa sinf ichida" |
| 1991 | Python — OOP bor, lekin majburiy emas |
Muammo: 1960-70-larda dasturlar kattalashdi. goto va global o'zgaruvchilar bilan 10 000 qatordan keyin hech kim tushunmasdi.
Yechim: kodni mustaqil, chegaralangan bo'laklarga bo'lish. Har bo'lak o'z ma'lumotini boshqaradi.
Alan Kay ning asl g'oyasi (u "object-oriented" atamasini o'ylab topgan):
"OOP menda faqat xabar almashish, lokal saqlash va himoya, va hamma narsani kech bog'lash degani edi."
Ko'p tillar (Java, C++) merosga urg'u berdi — Kay aytmagan narsaga. Bu — keyingi darslarda ko'radigan muammolarning sababi.
2.6. Qachon OOP kerak — va qachon kerak emas
OOP mos keladi:
# 1. Holat + xatti-harakat birga
class Ulanish:
def __init__(self, url):
self._soket = ulan(url)
def sorov(self, yol): ...
def yop(self): ...
# 2. Bir necha o'xshash turlar
class ToleForma: ...
class Karta(ToleForma): ...
class Naqd(ToleForma): ...
# 3. Invariant saqlash kerak
class Sana:
def __init__(self, kun, oy):
if not 1 <= oy <= 12:
raise ValueError(...)
# 4. Resurs boshqaruvi
class Fayl:
def __enter__(self): ...
def __exit__(self, *_): ...OOP ortiqcha:
# 1. Faqat bitta metod → funksiya yetadi
class Hisoblagich: # ⚠️
def hisobla(self, x): return x * 2
def hisobla(x): return x * 2 # ✅
# 2. Faqat ma'lumot → dataclass yoki NamedTuple
class Nuqta: # ⚠️ ko'p yozuv
def __init__(self, x, y):
self.x, self.y = x, y
@dataclass # ✅
class Nuqta:
x: float
y: float
# 3. "Menejer", "Ishlovchi", "Yordamchi" sinflari
class MalumotIshlovchiMenejer: # ⚠️ ot emas, fe'l
def qayta_ishla(self, d): ...
def qayta_ishla(d): ... # ✅
# 4. Global holatni yashirish
class Sozlamalar: # ⚠️ singleton — global
_nusxa = None Oddiy mezon: agar sinfda faqat __init__ va bitta metod bo'lsa — bu funksiya bo'lishi kerak.
2.7. OOP tanqidi
OOP — mukammal emas. Ma'lum muammolari:
1. Meros — mo'rt bog'lanish
class A:
def f(self): self.g()
def g(self): print("A.g")
class B(A):
def g(self): print("B.g") # A.f xatti-harakati o'zgardi
B().f() # "B.g" — kutilmaganBu — mo'rt asosiy sinf muammosi (fragile base class). Ota-sinf o'zgarsa — barcha avlodlar buzilishi mumkin.
2. O'zgaruvchan holat — bir vaqtli ish uchun xavfli
class Hisoblagich:
def __init__(self): self.n = 0
def oshir(self): self.n += 1 # ⚠️ thread-safe emas3. Ortiqcha abstraksiya
Java dunyosidagi mashhur hazil: AbstractSingletonProxyFactoryBean — haqiqiy Spring sinfi.
4. "Milliard dollarlik xato" ga yaqin
Ba'zi tanqidchilar (Joe Armstrong, Erlang muallifi):
"OOP muammosi shundaki, siz banan so'ragan edingiz, lekin bananni ushlab turgan gorilla va butun o'rmonni oldingiz."
Pythonning javobi: OOP — ixtiyoriy. Funksiya yetsa — funksiya yozing. Sinf kerak bo'lsa — sinf. Aralashtirish ham mumkin.
3. Tez ma'lumotnoma
To'rt ustun
Kapsulatsiya ma'lumot + kod birga, ichkarisi yashirin
Abstraksiya "nima" ko'rinadi, "qanday" yashirin
Meros yangi sinf mavjudini kengaytiradi
Polimorfizm bir interfeys — turli amalga oshirishSinf va obyekt
class Nom: # chizma
def __init__(self, x): # konstruktor
self.x = x # nusxa atributi
def metod(self): # xatti-harakat
return self.x
obyekt = Nom(5) # nusxa yaratish
obyekt.metod() # metod chaqirishHamma narsa obyekt
type(42) int
type(int) type ← sinf ham obyekt
type(type) type
id(x) identifikator
type(x) tur
x qiymatQachon sinf
✅ holat + xatti-harakat birga
✅ bir necha o'xshash tur
✅ invariant saqlash
✅ resurs boshqaruvi
❌ faqat bitta metod → funksiya
❌ faqat ma'lumot → dataclass / NamedTuple
❌ "Menejer", "Ishlovchi" → funksiya
❌ global holat → aniq uzatish4. Batafsil misollar
Misol 1 — Bir muammo, to'rt yondashuv
"""Bir vazifa — turli paradigmalarda."""
from dataclasses import dataclass, field
from functools import reduce
from typing import NamedTuple
print("=== VAZIFA: talabalar bahosini boshqarish ===\n")
MALUMOT = [
("Aziz", [90, 85, 78]),
("Malika", [95, 92, 88]),
("Bobur", [65, 70, 72]),
("Dilnoza", [88, 91, 94]),
]
print("=== 1. Protsedura yondashuvi ===\n")
talabalar_p = []
def talaba_qosh(ism, baholar):
talabalar_p.append({"ism": ism, "baholar": list(baholar)})
def ortacha(talaba):
b = talaba["baholar"]
return sum(b) / len(b) if b else 0.0
def baho_qosh(talaba, baho):
talaba["baholar"].append(baho)
def daraja(talaba):
o = ortacha(talaba)
return "A" if o >= 90 else "B" if o >= 80 else "C" if o >= 70 else "D"
for ism, baholar in MALUMOT:
talaba_qosh(ism, baholar)
for t in talabalar_p:
print(f" {t['ism']:<10} {ortacha(t):>6.1f} {daraja(t)}")
print(f"""
✅ Sodda, tez yozildi
⚠️ Ma'lumot va funksiya ajralgan
⚠️ t["blans"] kabi xato kalit — xato bermaydi
⚠️ baho_qosh(t, -50) — hech kim to'smaydi
⚠️ Global royxat (talabalar_p)
""")
# Muammo namoyishi
notogri = {"ism": "X", "bholar": [1]} # xato yozilgan kalit
try:
ortacha(notogri)
except KeyError as e:
print(f" Xato faqat ISH VAQTIDA: KeyError({e})\n")
print("=== 2. Funksional yondashuv ===\n")
class TalabaF(NamedTuple):
"""O'zgarmas — funksional uslub."""
ism: str
baholar: tuple[int, ...]
def ortacha_f(t: TalabaF) -> float:
return sum(t.baholar) / len(t.baholar) if t.baholar else 0.0
def baho_qosh_f(t: TalabaF, baho: int) -> TalabaF:
"""YANGI obyekt qaytaradi — eskisini o'zgartirmaydi."""
return t._replace(baholar=t.baholar + (baho,))
def daraja_f(o: float) -> str:
return next(d for chegara, d in
[(90, "A"), (80, "B"), (70, "C"), (0, "D")] if o >= chegara)
talabalar_f = tuple(TalabaF(ism, tuple(b)) for ism, b in MALUMOT)
for t in talabalar_f:
print(f" {t.ism:<10} {ortacha_f(t):>6.1f} {daraja_f(ortacha_f(t))}")
eski = talabalar_f[0]
yangi = baho_qosh_f(eski, 100)
print(f"""
O'zgarmaslik:
eski.baholar = {eski.baholar}
yangi.baholar = {yangi.baholar}
eski o'zgardimi? {'❌ yo`q' if eski.baholar == tuple(MALUMOT[0][1]) else 'ha'}
✅ Yon ta'sir yo'q, thread-safe
✅ Tur xavfsizligi (t.blans → AttributeError)
⚠️ Har o'zgarishda yangi obyekt (xotira)
⚠️ Invariant tekshiruvi yo'q
""")
print("=== 3. OOP yondashuvi ===\n")
class Talaba:
"""Baholarni boshqaradi va invariantni saqlaydi."""
ENG_KAM = 0
ENG_KOP = 100
def __init__(self, ism: str, baholar: list[int] | None = None):
if not ism.strip():
raise ValueError("Ism bo'sh bo'lmasin")
self.ism = ism
self._baholar: list[int] = []
for b in (baholar or []):
self.baho_qosh(b) # tekshiruvdan o'tkazamiz
def baho_qosh(self, baho: int) -> None:
if not self.ENG_KAM <= baho <= self.ENG_KOP:
raise ValueError(
f"Baho {self.ENG_KAM}–{self.ENG_KOP} oralig'ida bo'lsin: {baho}"
)
self._baholar.append(baho)
@property
def baholar(self) -> tuple[int, ...]:
"""Nusxa qaytaradi — tashqaridan o'zgartirib bo'lmaydi."""
return tuple(self._baholar)
@property
def ortacha(self) -> float:
return sum(self._baholar) / len(self._baholar) if self._baholar else 0.0
@property
def daraja(self) -> str:
o = self.ortacha
return "A" if o >= 90 else "B" if o >= 80 else "C" if o >= 70 else "D"
def __repr__(self) -> str:
return f"Talaba({self.ism!r}, {self._baholar})"
def __str__(self) -> str:
return f"{self.ism}: {self.ortacha:.1f} ({self.daraja})"
talabalar_o = [Talaba(ism, b) for ism, b in MALUMOT]
for t in talabalar_o:
print(f" {t}")
print(f"\n Himoya sinovi:")
t = talabalar_o[0]
SINOVLAR = [
("t.baho_qosh(150)", lambda: t.baho_qosh(150)),
("t.baho_qosh(-10)", lambda: t.baho_qosh(-10)),
("t.baholar.append(999)", lambda: t.baholar.append(999)),
("Talaba('')", lambda: Talaba("")),
("t.ortacha = 100", lambda: setattr(t, "ortacha", 100)),
]
for kod, f in SINOVLAR:
try:
f()
natija = "⚠️ o'tdi (himoya yo'q)"
except Exception as e:
natija = f"✅ {type(e).__name__}"
print(f" {kod:<26} {natija}")
print(f"""
✅ Invariant kafolatlangan (baho 0–100)
✅ Ichki ro'yxat himoyalangan
✅ Ma'lumot + xatti-harakat birga
⚠️ Ko'proq kod
""")
print("\n=== 4. dataclass — o'rta yo'l ===\n")
@dataclass
class TalabaD:
"""Kam kod, lekin sinf imkoniyatlari."""
ism: str
baholar: list[int] = field(default_factory=list)
@property
def ortacha(self) -> float:
return sum(self.baholar) / len(self.baholar) if self.baholar else 0.0
talabalar_d = [TalabaD(ism, list(b)) for ism, b in MALUMOT]
for t in talabalar_d:
print(f" {t.ism:<10} {t.ortacha:>6.1f}")
print(f"\n Bepul olingan:")
print(f" repr: {talabalar_d[0]}")
print(f" eq: {TalabaD('A', [1]) == TalabaD('A', [1])}")
print(f"""
✅ __init__, __repr__, __eq__ avtomatik
✅ Tur ko'rsatkichlari
⚠️ Invariant tekshiruvi yo'q (__post_init__ kerak)
""")
print("=== 5. Solishtirish ===\n")
print("""
┌──────────────┬────────┬───────────┬────────┬───────────┐
│ Mezon │ Protse.│ Funksional│ OOP │ dataclass │
├──────────────┼────────┼───────────┼────────┼───────────┤
│ Kod hajmi │ kam │ o'rta │ ko'p │ kam │
│ Invariant │ ❌ │ ❌ │ ✅ │ ⚠️ │
│ Tur xavfsiz. │ ❌ │ ✅ │ ✅ │ ✅ │
│ Thread-safe │ ❌ │ ✅ │ ❌ │ ❌ │
│ Kengaytirish │ ❌ │ ⚠️ │ ✅ │ ✅ │
│ Test qilish │ ⚠️ │ ✅ │ ⚠️ │ ✅ │
│ IDE yordami │ ❌ │ ✅ │ ✅ │ ✅ │
└──────────────┴────────┴───────────┴────────┴───────────┘
⭐ TANLASH:
Bir martalik skript → protsedura
Ma'lumot uzatish → NamedTuple / dataclass
Qoidalar va holat → sinf
Bir vaqtli ish, hisoblash → funksional
""")Natijaning muhim qismi:
=== 1. Protsedura yondashuvi ===
Aziz 84.3 B
Malika 91.7 A
Bobur 69.0 D
Xato faqat ISH VAQTIDA: KeyError('baholar')
=== 3. OOP yondashuvi ===
Aziz: 84.3 (B)
Malika: 91.7 (A)
Himoya sinovi:
t.baho_qosh(150) ✅ ValueError
t.baho_qosh(-10) ✅ ValueError
t.baholar.append(999) ✅ AttributeError
Talaba('') ✅ ValueError
t.ortacha = 100 ✅ AttributeErrorNima ko'rsatdi: 2.1, 2.2, 2.6-bo'limlar.
Misol 2 — Hamma narsa obyekt
"""Pythonda hamma narsa obyekt ekanining isboti."""
import sys
import types
print("=== 1. Har narsaning turi bor ===\n")
NARSALAR = [
("son", 42),
("float", 3.14),
("satr", "abc"),
("ro'yxat", [1, 2]),
("lug'at", {"a": 1}),
("to'plam", {1, 2}),
("tuple", (1, 2)),
("None", None),
("bool", True),
("funksiya", len),
("lambda", lambda x: x),
("sinf", int),
("modul", sys),
("tur", type),
("generator", (x for x in [1])),
("range", range(3)),
]
print(f" {'Nima':<12} {'type()':<32} {'id() bor':<10} {'metodlar'}")
print(" " + "─" * 68)
for nom, obj in NARSALAR:
tur = type(obj).__name__
metodlar = len([a for a in dir(obj) if not a.startswith("_")])
print(f" {nom:<12} {tur:<32} {'✅':<10} {metodlar}")
print("\n=== 2. Sonlar ham obyekt ===\n")
x = 42
AMALLAR = [
("x.bit_length()", lambda: x.bit_length()),
("x.to_bytes(2, 'big')", lambda: x.to_bytes(2, "big")),
("x.__add__(8)", lambda: x.__add__(8)),
("x.__str__()", lambda: x.__str__()),
("x.real, x.imag", lambda: (x.real, x.imag)),
("x.numerator", lambda: x.numerator),
("3.5-bob.is_integer()", lambda: (3.5).is_integer()),
("3.5-bob.hex()", lambda: (3.5).hex()),
("0.75-bob.as_integer_ratio()", lambda: (0.75).as_integer_ratio()),
]
for kod, f in AMALLAR:
print(f" {kod:<30} → {f()!r}")
print(f"""
⭐ 5 + 3 aslida:
(5).__add__(3) = {(5).__add__(3)}
⚠️ Lekin to'g'ridan-to'g'ri yozmang:
a + b ✅ a.__add__(b) ❌
(chunki + qo'shimcha qoidalarni ham bajaradi — 8.13-dars)
""")
print("=== 3. Funksiyalar ham obyekt ===\n")
def salom(ism: str) -> str:
"""Salomlashadi."""
return f"Salom, {ism}!"
ATRIBUTLAR = [
("__name__", salom.__name__),
("__doc__", salom.__doc__),
("__module__", salom.__module__),
("__annotations__", salom.__annotations__),
("__defaults__", salom.__defaults__),
("__code__.co_varnames", salom.__code__.co_varnames),
("__code__.co_argcount", salom.__code__.co_argcount),
]
for nom, qiymat in ATRIBUTLAR:
print(f" salom.{nom:<24} {qiymat!r}")
salom.chaqirilgan = 0 # ⭐ atribut qo'shish mumkin
salom.chaqirilgan += 1
print(f"\n salom.chaqirilgan = {salom.chaqirilgan} ← o'zimiz qo'shdik")
print(f" isinstance(salom, object) = {isinstance(salom, object)}")
print("\n=== 4. Sinflar ham obyekt ===\n")
print(f" type(int) = {type(int)}")
print(f" type(str) = {type(str)}")
print(f" type(type) = {type(type)} ← o'zi-o'ziga")
print(f" int.__name__ = {int.__name__!r}")
print(f" int.__bases__ = {int.__bases__}")
print(f" int.__mro__ = {int.__mro__}")
# Sinfni o'zgaruvchiga solish
T = int
print(f"\n T = int; T('42') = {T('42')!r}")
# Sinfni funksiyaga uzatish
def yarat(sinf, *args):
return sinf(*args)
print(f" yarat(list, [1,2]) = {yarat(list, [1, 2])}")
print(f" yarat(dict, [('a',1)]) = {yarat(dict, [('a', 1)])}")
# Sinfni ish vaqtida yaratish
Nuqta = type("Nuqta", (), {"x": 0, "y": 0,
"masofa": lambda self: (self.x**2 + self.y**2)**0.5})
n = Nuqta()
n.x, n.y = 3, 4
print(f"\n type() bilan yaratilgan sinf:")
print(f" Nuqta = type('Nuqta', (), {{...}})")
print(f" n.masofa() = {n.masofa()}")
print("\n=== 5. Uch xususiyat ===\n")
a = [1, 2, 3]
b = a
c = [1, 2, 3]
print(f" a = [1, 2, 3]")
print(f" b = a")
print(f" c = [1, 2, 3]\n")
print(f" {'':<6} {'id()':<18} {'type()':<10} {'qiymat'}")
print(" " + "─" * 48)
for nom, obj in [("a", a), ("b", b), ("c", c)]:
print(f" {nom:<6} {id(obj):<18} {type(obj).__name__:<10} {obj}")
print(f"""
a is b = {a is b} ← bir xil identifikator
a is c = {a is c} ← boshqa obyekt
a == c = {a == c} ← bir xil qiymat
⭐ is → identifikator (id)
== → qiymat (__eq__)
""")
print("=== 6. object — hamma narsaning otasi ===\n")
TURLAR = [int, float, str, list, dict, set, tuple, bool, type, object]
print(f" {'Tur':<10} {'object dan meros':<20} {'MRO uzunligi'}")
print(" " + "─" * 46)
for t in TURLAR:
meros = "✅" if issubclass(t, object) else "❌"
print(f" {t.__name__:<10} {meros:<20} {len(t.__mro__)}")
print(f"""
bool.__mro__ = {bool.__mro__}
⭐ bool — int dan meros! Shuning uchun:
True + True = {True + True}
isinstance(True, int) = {isinstance(True, int)}
""")
print(f" object da nechta atribut: {len(dir(object))}")
print(f" Ular: {', '.join(sorted(dir(object))[:8])}, ...")Natijaning muhim qismi:
=== 1. Har narsaning turi bor ===
Nima type() id() bor metodlar
────────────────────────────────────────────────────────────────────
son int ✅ 11
satr str ✅ 47
sinf type ✅ 11
modul module ✅ 79
tur type ✅ 1
=== 4. Sinflar ham obyekt ===
type(int) = <class 'type'>
type(type) = <class 'type'> ← o'zi-o'ziga
int.__mro__ = (<class 'int'>, <class 'object'>)
type() bilan yaratilgan sinf:
n.masofa() = 5.0
=== 6. object — hamma narsaning otasi ===
bool.__mro__ = (<class 'bool'>, <class 'int'>, <class 'object'>)
⭐ bool — int dan meros!
True + True = 2Nima ko'rsatdi: 2.3-bo'lim.
Misol 3 — Qachon sinf kerak emas
"""OOP ni ortiqcha ishlatish belgilari va tuzatishlar."""
from dataclasses import dataclass
from typing import NamedTuple
import math
print("=== ⚠️ ANTIPATTERN 1: bitta metodli sinf ===\n")
print(""" ❌ Yomon:
class SalomBeruvchi:
def __init__(self, ism):
self.ism = ism
def salom(self):
return f"Salom, {self.ism}!"
SalomBeruvchi("Aziz").salom()
✅ Yaxshi:
def salom(ism):
return f"Salom, {ism}!"
salom("Aziz")
⭐ MEZON: sinfda faqat __init__ va bitta metod bo'lsa —
bu funksiya bo'lishi kerak.
""")
class HisobKitobchi: # ❌
def __init__(self, foiz):
self.foiz = foiz
def hisobla(self, summa):
return summa * (1 + self.foiz / 100)
def foiz_qosh(summa, foiz): # ✅
return summa * (1 + foiz / 100)
print(f" Sinf: HisobKitobchi(10).hisobla(100) = "
f"{HisobKitobchi(10).hisobla(100)}")
print(f" Funksiya: foiz_qosh(100, 10) = {foiz_qosh(100, 10)}")
print(f"""
⚠️ Istisno: agar sozlama BIR MARTA berilib,
KO'P MARTA ishlatilsa — yopilma yoki partial yaxshiroq:
from functools import partial
ozbek_foizi = partial(foiz_qosh, foiz=10)
ozbek_foizi(100) → {math.floor(foiz_qosh(100, 10))}
""")
print("=== ⚠️ ANTIPATTERN 2: getter/setter sinfi ===\n")
class NuqtaYomon: # ❌
def __init__(self, x, y):
self._x = x
self._y = y
def get_x(self): return self._x
def set_x(self, v): self._x = v
def get_y(self): return self._y
def set_y(self, v): self._y = v
@dataclass # ✅
class Nuqta:
x: float
y: float
class NuqtaNT(NamedTuple): # ✅ o'zgarmas
x: float
y: float
print(f" ❌ NuqtaYomon: 4 metod, hech qanday mantiq — 12 qator")
print(f" ✅ dataclass: 2 qator, __repr__ va __eq__ bepul")
print(f" ✅ NamedTuple: 2 qator, o'zgarmas, tuple kabi ishlaydi\n")
p1, p2 = Nuqta(1, 2), Nuqta(1, 2)
n1 = NuqtaNT(3, 4)
print(f" Nuqta(1,2) == Nuqta(1,2) → {p1 == p2}")
print(f" repr: {p1}")
print(f" NamedTuple ochish: x, y = n1 → {tuple(n1)}")
print(f"""
⭐ Pythonda getter/setter KERAK EMAS:
• Ochiq atribut yozing
• Keyin nazorat kerak bo'lsa — @property qo'shasiz
• Chaqiruvchi kod O'ZGARMAYDI
class Nuqta:
@property
def x(self): return self._x # keyin qo'shildi
p.x ← bir xil ishlatiladi
""")
print("=== ⚠️ ANTIPATTERN 3: 'Menejer' sinflari ===\n")
print(""" ❌ Yomon (nomi FE'L — bu funksiya belgisi):
class MalumotIshlovchi:
class FaylOquvchi:
class HisobotYaratuvchi:
class SozlamaBoshqaruvchi:
class ValidatsiyaMenejeri:
✅ Yaxshi (nomi OT — haqiqiy narsa):
class Hujjat:
class Ulanish:
class Buyurtma:
class Sana:
⭐ TEST: sinf nomini ot deb ayta olasizmi?
"Bir dona MalumotIshlovchi" ⚠️ g'alati
"Bir dona Hujjat" ✅ tabiiy
Fe'l nomli sinflar odatda modul bo'lishi kerak:
# malumot_ishlash.py
def yukla(yol): ...
def tozala(m): ...
def saqla(m, yol): ...
""")
print("=== ⚠️ ANTIPATTERN 4: sinf ichida global holat ===\n")
class SozlamalarYomon: # ❌ singleton
_nusxa = None
_malumot = {}
def __new__(cls):
if cls._nusxa is None:
cls._nusxa = super().__new__(cls)
return cls._nusxa
def olish(self, kalit):
return self._malumot.get(kalit)
s1 = SozlamalarYomon()
s2 = SozlamalarYomon()
print(f" s1 is s2 = {s1 is s2} ← har doim bir obyekt")
print("""
⚠️ Muammolar:
• Bu — chiroyli qadoqlangan GLOBAL o'zgaruvchi
• Testlarda holat testdan testga o'tadi
• Bir vaqtli ishda xavfli
• Bog'liqlik yashirin (kim ishlatayotgani ko'rinmaydi)
✅ Yaxshi — aniq uzatish:
@dataclass(frozen=True)
class Sozlamalar:
url: str
chegara: int = 100
def ishla(malumot, sozlamalar: Sozlamalar):
...
# Testda:
ishla(m, Sozlamalar(url="test://", chegara=5))
""")
print("=== ⚠️ ANTIPATTERN 5: chuqur meros ===\n")
print(""" ❌ Yomon:
Obyekt → Jonzot → Hayvon → Sutemizuvchi → Yirtqich
→ Mushuksimon → Katta → Sher
• 7 daraja — self.f() qayerdan kelganini topib bo'lmaydi
• Ota-sinf o'zgarsa — hammasi buziladi
• Yangi holat mos kelmasa (uchadigan sher?) — qayta yozish
✅ Yaxshi — kompozitsiya:
@dataclass
class Hayvon:
nom: str
ovqatlanish: OvqatlanishUsuli
harakat: HarakatUsuli
sher = Hayvon("Sher", Yirtqich(), Yugurish())
burgut = Hayvon("Burgut", Yirtqich(), Uchish())
⭐ QOIDA: meros chuqurligi ≤ 2–3 daraja.
Bundan chuqur bo'lsa — kompozitsiyani ko'rib chiqing (8.20-dars).
""")
print("=== ✅ QACHON SINF TO'G'RI ===\n")
class Sana:
"""✅ Invariant + xatti-harakat + turlararo amallar."""
KUNLAR = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
def __init__(self, kun: int, oy: int, yil: int):
if not 1 <= oy <= 12:
raise ValueError(f"Oy 1–12: {oy}")
maks = self.KUNLAR[oy - 1] + (
1 if oy == 2 and self._kabisa(yil) else 0)
if not 1 <= kun <= maks:
raise ValueError(f"{oy}-oyda {maks} kun bor: {kun}")
self.kun, self.oy, self.yil = kun, oy, yil
@staticmethod
def _kabisa(yil: int) -> bool:
return yil % 4 == 0 and (yil % 100 != 0 or yil % 400 == 0)
def __repr__(self) -> str:
return f"Sana({self.kun}, {self.oy}, {self.yil})"
def __str__(self) -> str:
return f"{self.kun:02d}.{self.oy:02d}.{self.yil}"
def __eq__(self, boshqa) -> bool:
if not isinstance(boshqa, Sana):
return NotImplemented
return (self.yil, self.oy, self.kun) == \
(boshqa.yil, boshqa.oy, boshqa.kun)
def __lt__(self, boshqa) -> bool:
if not isinstance(boshqa, Sana):
return NotImplemented
return (self.yil, self.oy, self.kun) < \
(boshqa.yil, boshqa.oy, boshqa.kun)
SINOVLAR = [
("Sana(15, 3, 2026)", lambda: Sana(15, 3, 2026)),
("Sana(31, 2, 2026)", lambda: Sana(31, 2, 2026)),
("Sana(29, 2, 2024)", lambda: Sana(29, 2, 2024)),
("Sana(29, 2, 2026)", lambda: Sana(29, 2, 2026)),
("Sana(1, 13, 2026)", lambda: Sana(1, 13, 2026)),
]
for kod, f in SINOVLAR:
try:
natija = f"✅ {f()}"
except ValueError as e:
natija = f"❌ {e}"
print(f" {kod:<24} {natija}")
sanalar = [Sana(15, 3, 2026), Sana(1, 1, 2026), Sana(31, 12, 2025)]
print(f"\n Saralash (__lt__ tufayli): "
f"{[str(s) for s in sorted(sanalar)]}")
print("""
⭐ Bu sinf O'RINLI, chunki:
1. Invariant bor (kun oyga mos bo'lishi kerak)
2. Xatti-harakat bor (taqqoslash, formatlash)
3. Bir necha metod ma'noli bog'langan
4. Tur o'zi ma'no beradi (Sana ≠ tuple)
""")Natijaning muhim qismi:
=== ⚠️ ANTIPATTERN 1: bitta metodli sinf ===
Sinf: HisobKitobchi(10).hisobla(100) = 110.00000000000001
Funksiya: foiz_qosh(100, 10) = 110.00000000000001
=== ⚠️ ANTIPATTERN 4: sinf ichida global holat ===
s1 is s2 = True ← har doim bir obyekt
=== ✅ QACHON SINF TO'G'RI ===
Sana(15, 3, 2026) ✅ 15.03.2026
Sana(31, 2, 2026) ❌ 2-oyda 28 kun bor: 31
Sana(29, 2, 2024) ✅ 29.02.2024
Sana(29, 2, 2026) ❌ 2-oyda 28 kun bor: 29
Sana(1, 13, 2026) ❌ Oy 1–12: 13
Saralash (__lt__ tufayli): ['31.12.2025', '01.01.2026', '15.03.2026']Nima ko'rsatdi: 2.6, 2.7-bo'limlar.
Misol 4 — To'rt ustunni ko'rish
"""Kapsulatsiya, abstraksiya, meros, polimorfizm — bir misolda."""
from abc import ABC, abstractmethod
from dataclasses import dataclass
import math
print("=== 1️⃣ KAPSULATSIYA ===\n")
class Termostat:
"""Harorat nazorati — ichki holat himoyalangan."""
MIN, MAKS = 5.0, 35.0
def __init__(self, boshlangich: float = 20.0):
self._harorat = 0.0
self._tarix: list[float] = []
self.orn(boshlangich) # tekshiruvdan o'tadi
def orn(self, qiymat: float) -> None:
"""Haroratni o'rnatadi (chegaralar ichida)."""
if not self.MIN <= qiymat <= self.MAKS:
raise ValueError(
f"Harorat {self.MIN}–{self.MAKS}°C oralig'ida: {qiymat}"
)
self._harorat = qiymat
self._tarix.append(qiymat)
def oshir(self, daraja: float = 1.0) -> None:
self.orn(min(self._harorat + daraja, self.MAKS))
def pasaytir(self, daraja: float = 1.0) -> None:
self.orn(max(self._harorat - daraja, self.MIN))
@property
def harorat(self) -> float:
return self._harorat
@property
def tarix(self) -> tuple[float, ...]:
return tuple(self._tarix) # nusxa — buzib bo'lmaydi
t = Termostat(22)
t.oshir(3)
t.pasaytir(1)
t.oshir(50) # MAKS da to'xtaydi
print(f" Joriy harorat: {t.harorat}°C")
print(f" Tarix: {t.tarix}")
print(f"\n Himoya:")
for kod, f in [
("t.orn(100)", lambda: t.orn(100)),
("t.orn(-5)", lambda: t.orn(-5)),
("t.tarix.append(99)", lambda: t.tarix.append(99)),
("t.harorat = 99", lambda: setattr(t, "harorat", 99)),
]:
try:
f(); n = "⚠️ o'tdi"
except Exception as e:
n = f"✅ {type(e).__name__}"
print(f" {kod:<22} {n}")
print(f"""
⭐ Kapsulatsiya bergan kafolat:
_harorat DOIM {Termostat.MIN}–{Termostat.MAKS} oralig'ida.
Bu — INVARIANT. Sinf tashqarisidagi hech qanday kod
uni buza olmaydi.
""")
print("=== 2️⃣ ABSTRAKSIYA ===\n")
class Ombor(ABC):
"""Ma'lumot saqlash interfeysi — QANDAY saqlanishi muhim emas."""
@abstractmethod
def saqla(self, kalit: str, qiymat: str) -> None: ...
@abstractmethod
def olish(self, kalit: str) -> str | None: ...
def olish_yoki(self, kalit: str, sukut: str) -> str:
"""Umumiy mantiq — bir marta yoziladi."""
q = self.olish(kalit)
return sukut if q is None else q
class XotiraOmbor(Ombor):
def __init__(self):
self._m: dict[str, str] = {}
def saqla(self, kalit, qiymat):
self._m[kalit] = qiymat
def olish(self, kalit):
return self._m.get(kalit)
class JurnalliOmbor(Ombor):
"""Har amalni yozib boradi."""
def __init__(self, ichki: Ombor):
self._ichki = ichki
self.jurnal: list[str] = []
def saqla(self, kalit, qiymat):
self.jurnal.append(f"SAQLA {kalit}={qiymat}")
self._ichki.saqla(kalit, qiymat)
def olish(self, kalit):
self.jurnal.append(f"OLISH {kalit}")
return self._ichki.olish(kalit)
def foydalanuvchi_ishi(ombor: Ombor) -> str:
"""⭐ Bu funksiya QANDAY omborni bilmaydi."""
ombor.saqla("til", "python")
ombor.saqla("versiya", "3.12")
return f"{ombor.olish('til')} {ombor.olish_yoki('versiya', '?')}"
x = XotiraOmbor()
j = JurnalliOmbor(XotiraOmbor())
print(f" XotiraOmbor: {foydalanuvchi_ishi(x)}")
print(f" JurnalliOmbor: {foydalanuvchi_ishi(j)}")
print(f"\n Jurnal:")
for q in j.jurnal:
print(f" {q}")
print(f"""
⭐ foydalanuvchi_ishi() o'zgarmadi, lekin xatti-harakat
butunlay boshqacha. Bu — abstraksiya kuchi.
""")
print("=== 3️⃣ MEROS ===\n")
class Xodim:
def __init__(self, ism: str, maosh: float):
self.ism = ism
self.maosh = maosh
def oylik(self) -> float:
return self.maosh
def tavsif(self) -> str:
return f"{self.ism} ({type(self).__name__})"
class Menejer(Xodim):
def __init__(self, ism, maosh, jamoa: int):
super().__init__(ism, maosh) # ota-konstruktor
self.jamoa = jamoa
def oylik(self) -> float:
return super().oylik() + self.jamoa * 50_000 # ustama
class Sotuvchi(Xodim):
def __init__(self, ism, maosh, sotuv: float, foiz: float = 5):
super().__init__(ism, maosh)
self.sotuv, self.foiz = sotuv, foiz
def oylik(self) -> float:
return super().oylik() + self.sotuv * self.foiz / 100
class Stajyor(Xodim):
def oylik(self) -> float:
return self.maosh * 0.5
XODIMLAR = [
Xodim("Aziz", 5_000_000),
Menejer("Malika", 8_000_000, jamoa=6),
Sotuvchi("Bobur", 4_000_000, sotuv=30_000_000),
Stajyor("Dilnoza", 3_000_000),
]
print(f" {'Xodim':<28} {'Asosiy':>14} {'Oylik':>14}")
print(" " + "─" * 58)
for x in XODIMLAR:
print(f" {x.tavsif():<28} {x.maosh:>14,.0f} {x.oylik():>14,.0f}")
print(f"\n Meros zanjiri:")
for sinf in [Xodim, Menejer, Sotuvchi, Stajyor]:
zanjir = " → ".join(c.__name__ for c in sinf.__mro__)
print(f" {zanjir}")
print(f"""
⭐ tavsif() faqat BIR MARTA yozilgan (Xodim da),
lekin to'rt sinfda ham ishlaydi.
⭐ super().oylik() ota-sinf mantiqini QAYTA ISHLATADI.
""")
print("=== 4️⃣ POLIMORFIZM ===\n")
@dataclass
class Doira:
r: float
def yuza(self) -> float: return math.pi * self.r ** 2
def perimetr(self) -> float: return 2 * math.pi * self.r
@dataclass
class Togriturtburchak:
a: float
b: float
def yuza(self) -> float: return self.a * self.b
def perimetr(self) -> float: return 2 * (self.a + self.b)
@dataclass
class Uchburchak:
a: float
b: float
c: float
def yuza(self) -> float:
p = (self.a + self.b + self.c) / 2
return math.sqrt(p * (p-self.a) * (p-self.b) * (p-self.c))
def perimetr(self) -> float: return self.a + self.b + self.c
SHAKLLAR = [Doira(5), Togriturtburchak(4, 6), Uchburchak(3, 4, 5)]
print(f" {'Shakl':<32} {'Yuza':>10} {'Perimetr':>10}")
print(" " + "─" * 54)
for s in SHAKLLAR:
print(f" {str(s):<32} {s.yuza():>10.2f} {s.perimetr():>10.2f}")
jami = sum(s.yuza() for s in SHAKLLAR)
eng_katta = max(SHAKLLAR, key=lambda s: s.yuza())
print(f"\n Jami yuza: {jami:.2f}")
print(f" Eng katta: {eng_katta}")
print(f"""
⭐ MUHIM: bu uch sinf HECH NARSADAN meros olmagan!
Polimorfizm Pythonda MEROS talab qilmaydi —
bir xil metod nomi yetadi. Bu — DUCK TYPING.
⭐ O'rnatilgan polimorfizm misollari:
len() — str, list, dict, set, ... hammasida
+ — son, satr, ro'yxat, ...
for — har qanday iterable
print() — har qanday obyekt (__str__)
""")
print(f" len() polimorfizmi:")
for x in ["abcde", [1, 2, 3], {"a": 1}, {1, 2}, (1,), range(7), b"xy"]:
print(f" len({x!r:<16}) = {len(x)} ({type(x).__name__})")
print(f"\n + polimorfizmi:")
for a, b in [(1, 2), (1.5, 2.5), ("ab", "cd"), ([1], [2]), ((1,), (2,))]:
print(f" {a!r:<8} + {b!r:<8} = {a + b!r}")
print("\n=== YAKUN: to'rt ustun birga ===\n")
print("""
┌─────────────────┬──────────────────────────────────────────┐
│ Ustun │ Nima beradi │
├─────────────────┼──────────────────────────────────────────┤
│ Kapsulatsiya │ Invariant kafolati, xavfsiz o'zgartirish │
│ Abstraksiya │ Amalga oshirishni almashtirish erkinligi │
│ Meros │ Kodni qayta ishlatish, umumiy shartnoma │
│ Polimorfizm │ Bir kod — ko'p tur bilan ishlaydi │
└─────────────────┴──────────────────────────────────────────┘
⚠️ PYTHONDA:
• Kapsulatsiya — kelishuv (_ va __), majburlash emas
• Meros — foydali, lekin kompozitsiya ko'pincha yaxshiroq
• Polimorfizm — duck typing orqali, merossiz ham
• Abstraksiya — ABC yoki Protocol bilan
""")Natijaning muhim qismi:
=== 1️⃣ KAPSULATSIYA ===
Joriy harorat: 35.0°C
Tarix: (22, 25, 24, 35.0)
Himoya:
t.orn(100) ✅ ValueError
t.tarix.append(99) ✅ AttributeError
t.harorat = 99 ✅ AttributeError
=== 3️⃣ MEROS ===
Xodim Asosiy Oylik
──────────────────────────────────────────
Aziz (Xodim) 5,000,000 5,000,000
Malika (Menejer) 8,000,000 8,300,000
Bobur (Sotuvchi) 4,000,000 5,500,000
Dilnoza (Stajyor) 3,000,000 1,500,000
=== 4️⃣ POLIMORFIZM ===
Doira(r=5) 78.54 31.42
Togriturtburchak(a=4, b=6) 24.00 20.00
Uchburchak(a=3, b=4, c=5) 6.00 12.00Nima ko'rsatdi: 2.2-bo'lim.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "OOP — eng yaxshi paradigma" | Vosita. Muammoga qarab tanlanadi |
| "Hamma kod sinf ichida bo'lsin" | Java qoidasi. Pythonda funksiya ham to'liq huquqli |
| "Polimorfizm meros talab qiladi" | Pythonda duck typing yetadi |
| "Pythonda OOP yo'q" | Bor va to'liq — type, __mro__, metaklasslar |
| "Sinf — faqat ma'lumot idishi" | Ma'lumot uchun dataclass/NamedTuple |
| "Meros — asosiy OOP vositasi" | Kompozitsiya ko'pincha yaxshiroq (8.20) |
"private bo'lmasa kapsulatsiya yo'q" |
Kelishuv (_) amalda yetarli ishlaydi |
| "OOP sekinroq" | Atribut qidiruvi biroz sekin, lekin bu kamdan-kam muhim |
6. Keng tarqalgan xatolar va yechimlari
1. Har narsa uchun sinf
class Yigindi: # ❌
def hisobla(self, a, b): return a + b
def yigindi(a, b): return a + b # ✅2. Fe'l nomli sinflar
class MalumotIshlovchi: ... # ❌
class Hujjat: ... # ✅ ot3. Getter/setter yozish
def get_x(self): return self._x # ❌ Java uslubi
self.x = x # ✅ keyin @property qo'shasiz4. Chuqur meros
A → B → C → D → E → F # ❌ 6 daraja
A → B # ✅ 2 daraja5. Ma'lumot uchun to'liq sinf
class Nuqta: # ⚠️ 8 qator
def __init__(self, x, y): ...
def __repr__(self): ...
def __eq__(self, o): ...
@dataclass # ✅ 3 qator
class Nuqta:
x: float
y: float6. Ichki ro'yxatni qaytarish
@property
def elementlar(self): return self._el # ⚠️ tashqaridan o'zgartiriladi
@property
def elementlar(self): return tuple(self._el) # ✅7. Konstruktorda tekshirmaslik
def __init__(self, yosh):
self.yosh = yosh # ⚠️ -5 ham o'tadi
def __init__(self, yosh):
if yosh < 0: raise ValueError(...) # ✅
self.yosh = yosh8. Singleton bilan globalni yashirish
class Sozlamalar: # ⚠️ global
_nusxa = None
def ishla(m, sozlamalar: Sozlamalar): ... # ✅ aniq uzatish7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8.2-8.20-darslar: butun qism shu asosga quriladi
- 7-qism (o'tilgan): metodlar — bu
selfoladigan funksiyalar - 6-qism:
list,dict— bularning hammasi sinf - 9-qism: istisnolar ham sinflar (
Exceptiondan meros) - 10-qism: dekoratorlar sinflarga ham qo'llanadi
- 23-qism: ORM (Prisma, SQLAlchemy) — jadval = sinf
- Kitob: Fluent Python (Luciano Ramalho) — Python obyekt modeli
8. Eng yaxshi amaliyotlar
Sinf — ot, metod — fe'l.
Hujjat.saqla(),MalumotIshlovchi.ishla()emas.Faqat bitta metod bo'lsa — funksiya yozing. Sinf ortiqcha qatlam.
Faqat ma'lumot bo'lsa —
dataclassyokiNamedTuple.Konstruktorda invariantni tekshiring. Noto'g'ri obyekt umuman yaratilmasin.
Getter/setter yozmang. Ochiq atribut → keyin kerak bo'lsa
@property.Meros chuqurligi ≤ 2–3 daraja. Chuqur bo'lsa — kompozitsiya.
Ichki konteynerni nusxa qilib qaytaring.
tuple(self._el).Paradigmani aralashtiring. Pythonda bu — kuch, kamchilik emas.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
1. print(type(42), type(int), type(type))
2. print(isinstance(True, int))
3. print(True + True + True)
4. print((5).__add__(3))
5. class A: pass
a1, a2 = A(), A()
print(a1 == a2, a1 is a2)
6. class A:
x = 1
print(A.x, A().x)
7. def f(): pass
f.n = 5
print(f.n)
8. print(int.__mro__)
9. print(len([a for a in dir(int) if not a.startswith("_")]))
10. class A: pass
print(A.__bases__)
11. T = type("B", (), {"x": 7})
print(T().x)
12. print(issubclass(bool, int), issubclass(int, bool))Javoblar
<class 'int'> <class 'type'> <class 'type'>True—boolintdan meros3—True= 18False False— sukut bo'yicha==iskabi ishlaydi,a1vaa2esa alohida obyektlar1 1— sinf atributi nusxa orqali ham ko'rinadi5— funksiyaga atribut qo'shish mumkin(<class 'int'>, <class 'object'>)11— metodlar (bit_length,bit_count,to_bytes,from_bytes,as_integer_ratio,is_integer,conjugate) va atributlar (real,imag,numerator,denominator) —intham to'liq obyekt(<class 'object'>,)7True False
Vazifa 2: Sinf kerakmi?
Har holat uchun ayting — sinf, funksiya, dataclass yoki modul?
1. Ikki sonni qo'shish
2. Bank hisobi (balans, o'tkazmalar, tarix)
3. RGB rang (r, g, b qiymatlari)
4. Matn tozalash uchun 10 ta funksiya
5. Ma'lumotlar bazasi ulanishi (ochish, so'rov, yopish)
6. Foydalanuvchi ma'lumoti (ism, email, yosh)
7. Sana (kun, oy, yil + taqqoslash + formatlash)
8. Faylni JSON ga o'girishJavoblar
- Funksiya — holat yo'q
- Sinf — invariant (manfiy balans yo'q) + xatti-harakat
- NamedTuple / frozen dataclass — o'zgarmas ma'lumot
- Modul — funksiyalar to'plami, umumiy holat yo'q
- Sinf — resurs boshqaruvi,
__enter__/__exit__ - dataclass — asosan ma'lumot
- Sinf — invariant + taqqoslash + formatlash
- Funksiya — bir amal
Vazifa 3: Refaktoring
Bu kodni sinfga o'giring va invariantni qo'shing:
savat = {"mahsulotlar": [], "chegirma": 0}
def qosh(s, nom, narx, soni):
s["mahsulotlar"].append({"nom": nom, "narx": narx, "soni": soni})
def jami(s):
j = sum(m["narx"] * m["soni"] for m in s["mahsulotlar"])
return j * (1 - s["chegirma"] / 100)Talablar: narx va soni musbat, chegirma 0-100, mahsulotlar tashqaridan o'zgarmasin.
Vazifa 4: To'rt ustun
Kutubxona tizimi yozing:
Kitob— nom, muallif, ISBN (invariant: ISBN 13 raqam)Kutubxona— kitoblarni saqlaydi (kapsulatsiya)RaqamliKitob(Kitob)— hajm, format qo'shadi (meros)- Barcha kitob turlarida
tavsif()(polimorfizm) Omborabstrakt sinfi — xotira va fayl versiyalari (abstraksiya)
Vazifa 5: Antipattern topish
Quyidagilardagi muammoni ayting va tuzating:
1. class StringYordamchi:
@staticmethod
def tozala(s): return s.strip()
2. class Konfiguratsiya:
_nusxa = None
def __new__(cls): ...
3. class Foydalanuvchi:
def get_ism(self): return self._ism
def set_ism(self, v): self._ism = v
4. class A: pass
class B(A): pass
class C(B): pass
class D(C): pass
class E(D): passVazifa 6: Paradigma solishtirish
Bir vazifani (masalan, matndagi so'zlarni sanash) to'rt usulda yozing:
- Protsedura
- Funksional
- OOP
dataclassbilan
Har birining kod hajmi, o'qilishi va test qilinishini solishtiring.
Vazifa 7: O'ylash
Nega Alan Kay (OOP atamasining muallifi) keyinchalik aytdi: "Men 'obyektlar' deganimda uyaldim, chunki bu ko'pchilikni kichikroq g'oyaga olib bordi"?
Javob
Chunki asosiy g'oya obyektlar emas, xabar almashish edi.
Kay ning asl g'oyasi (Smalltalk, 1970-lar):
Kay biologiyadan ilhomlangan. Uning modeli — hujayralar:
- Har hujayra o'z ichini to'liq boshqaradi
- Hujayralar bir-biriga kimyoviy signal yuboradi
- Hech bir hujayra boshqasining ichiga kira olmaydi
- Signal olgan hujayra o'zi hal qiladi nima qilishni
Uch tamoyil:
- Xabar almashish (messaging) — asosiy narsa
- Lokal saqlash va himoya — ichkarisi to'liq yopiq
- Hamma narsani kech bog'lash (late binding)
"OOP menda faqat xabar almashish, lokal saqlash va himoya, va hamma narsani kech bog'lash degani edi. Buni Smalltalk va LISP da qilish mumkin. Boshqa tizimlar ham mumkindir, lekin men bilmayman."
Nima noto'g'ri ketdi:
C++ (1983) va Java (1995) OOP ni ommalashtirdi, lekin boshqa narsaga urg'u berdi:
| Kay aytgan | Sanoat oldi |
|---|---|
| Xabar almashish | Metod chaqirish |
| Kech bog'lash | Erta bog'lash, statik turlar |
| Hujayra kabi mustaqillik | Meros ierarxiyasi |
| Obyekt — jarayon | Obyekt — ma'lumot idishi |
Farq nimada?
# Metod chaqirish (sanoat OOP)
obyekt.metod(arg)
# → kompilyator/interpretator metod BORLIGINI biladi
# → yo'q bo'lsa xato
# Xabar yuborish (Kay ning g'oyasi)
obyekt.xabar_qabul_qil("metod", arg)
# → obyekt O'ZI hal qiladi nima qilishni
# → tushunmasa — o'zi javob beradi, tizim yiqilmaydiSmalltalk da doesNotUnderstand: bor edi — obyekt tanimagan xabarni o'zi qayta ishlaydi.
Pythonda bu g'oyaning izlari bor:
class Dinamik:
def __getattr__(self, nom):
"""⭐ Bu — 'doesNotUnderstand:' ning Python versiyasi."""
def ishlovchi(*args):
return f"Xabar '{nom}' qabul qilindi: {args}"
return ishlovchi
d = Dinamik()
d.hech_qachon_yozilmagan_metod(1, 2)
# 'Xabar 'hech_qachon_yozilmagan_metod' qabul qilindi: (1, 2)'Bu — kech bog'lash. ORM lar (user.filter_by_email()), RPC mijozlari, mock obyektlar shunday ishlaydi.
Meros — Kay aytmagan narsa
Sanoat OOP merosga eng ko'p urg'u berdi. Natija:
- Chuqur ierarxiyalar
- Mo'rt asosiy sinf muammosi
- "Kvadrat — Togriturtburchakmi?" (Liskov muammosi)
AbstractSingletonProxyFactoryBean
Kay merosni umuman ta'kidlamagan. Uning uchun muhimi — obyektlar bir-birining ichini bilmasligi edi.
Zamonaviy tasdiq:
Kay ning g'oyasi qayerda tirik qoldi?
| Texnologiya | Kay ning qaysi g'oyasi |
|---|---|
| Mikroservislar | Mustaqil, xabar (HTTP/queue) orqali muloqot |
| Erlang/Elixir aktyorlari | Aynan xabar almashish, umumiy holat yo'q |
| React komponentlari | Lokal holat, props orqali muloqot |
| Docker konteynerlari | To'liq izolyatsiya, tarmoq orqali |
Joe Armstrong (Erlang):
"Erlang — yagona to'g'ri OOP tili bo'lsa kerak."
Chunki Erlang da aktyorlar umumiy xotirasiz, faqat xabar orqali gaplashadi — Kay ning modeliga eng yaqin.
Amaliy xulosa Python uchun:
- Interfeysga tayaning, ichki tuzilmaga emas —
Protocol, ABC - Merosdan ko'ra kompozitsiya — obyektlarni birlashtiring
- Kech bog'lash — foydali —
__getattr__, duck typing - Kichik, mustaqil obyektlar — chuqur ierarxiyadan yaxshi
# ⚠️ Sanoat OOP — chuqur ierarxiya
class Hayvon: ...
class Sutemizuvchi(Hayvon): ...
class Yirtqich(Sutemizuvchi): ...
class Mushuksimon(Yirtqich): ...
class Sher(Mushuksimon): ...
# ✅ Kay ga yaqin — mustaqil qismlar
@dataclass
class Hayvon:
nom: str
ovqatlanish: Ovqatlanish # alohida obyekt
harakat: Harakat # alohida obyekt
ovoz: Ovoz # alohida obyektKay ning uyalishi — atama muvaffaqiyatli bo'lgani, lekin noto'g'ri qism ommalashgani uchun edi.
Nimani mustahkamlaydi: 2.2, 2.5, 2.7-bo'limlar.
Xulosa
Bu darsda OOP ning mohiyatini o'rgandik.
Eng muhim uch fikr:
OOP — ma'lumot va uni o'zgartiruvchi kodni birlashtirish. Buning natijasi — invariant: sinf tashqarisidagi kod obyektni noto'g'ri holatga keltira olmaydi. Kapsulatsiya, abstraksiya, meros va polimorfizm shunga xizmat qiladi.
Pythonda hamma narsa obyekt — sonlar, satrlar, funksiyalar, hatto sinflar va
typening o'zi.42ning metodlari bor,intni o'zgaruvchiga solish mumkin, sinfni ish vaqtida yaratsa bo'ladi. Siz OOP dan birinchi darsdan beri foydalanyapsiz.OOP — ixtiyoriy vosita. Bitta metodli sinf — funksiya bo'lishi kerak, faqat ma'lumot bo'lsa —
dataclass. Sinf invariant, xatti-harakat va holat birga bo'lganda o'rinli. Pythonda paradigmalarni aralashtirish — kuch, kamchilik emas.
Keyingi darsda sinf va obyektni amalda yozamiz: class sintaksisi, nusxa yaratish, atributlar va ular xotirada qanday saqlanishi.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!