Mundarija (21)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Uch metod turi
- 2.2. Fabrika metodlari — asosiy qo'llanish
- 2.3. Fabrika naqshlari
- 2.4. classmethod va sinf holati
- 2.5. @staticmethod — qachon kerak
- 2.6. Ikkalasi ham deskriptor
- 2.7. Kombinatsiyalar va cheklovlar
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Uch tur va deskriptorlar
- Misol 2 — Fabrika metodlari
- Misol 3 — @staticmethod — qachon kerak
- Misol 4 — Amaliy: plagin tizimi
- 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.16-dars: @staticmethod va @classmethod
8-QISM — OBYEKTGA YO'NALTIRILGAN DASTURLASH · 16-dars
1. Kirish va motivatsiya
Bu ikki metod deyarli bir xil ko'rinadi:
class Sana:
@staticmethod
def bugun_static():
return Sana(15, 3, 2026) # ⚠️ sinf nomi qattiq yozilgan
@classmethod
def bugun_class(cls):
return cls(15, 3, 2026) # ⭐ haqiqiy sinfFarq avlod sinfda ko'rinadi:
class UzbekSana(Sana):
pass
type(UzbekSana.bugun_static()) # Sana ⚠️
type(UzbekSana.bugun_class()) # UzbekSana ✅Va bu chalkash:
class A:
@staticmethod
def f(): return "static"
@classmethod
def g(cls): return f"class: {cls.__name__}"
A.f() # 'static'
A().f() # 'static'
A.g() # 'class: A'
A().g() # 'class: A' ⭐ nusxa emas
type(A.__dict__["f"]) # <class 'staticmethod'>
type(A.f) # <class 'function'> ⭐ farqli!Bu darsda:
-
clsvaself— nima farqi - Fabrika metodlari — asosiy qo'llanish
- Meros va
cls()ning ahamiyati @staticmethod— qachon haqiqatan kerak- Ikkalasi ham deskriptor ekani
classmethodbilan sinf holatini boshqarish
2. Nazariya — chuqur tushuntirish
2.1. Uch metod turi
class A:
def nusxa(self): ... # self — NUSXA
@classmethod
def sinf(cls): ... # cls — SINF
@staticmethod
def statik(): ... # hech narsa| Birinchi param | A.f() |
A().f() |
Meros | |
|---|---|---|---|---|
| Nusxa metod | self |
TypeError |
self — avlod nusxasi |
|
@classmethod |
cls |
cls — avlod sinf |
||
@staticmethod |
— | — |
cls — chaqirilgan sinf, aniqlangan sinf emas:
class Ota:
@classmethod
def kim(cls): return cls.__name__
class Bola(Ota): pass
Ota.kim() # 'Ota'
Bola.kim() # 'Bola' ⭐
Bola().kim() # 'Bola' ⭐ nusxadan ham2.2. Fabrika metodlari — asosiy qo'llanish
__init__ — bitta yo'l. Boshqa yo'llar @classmethod:
class Sana:
def __init__(self, kun, oy, yil): ...
@classmethod
def satrdan(cls, s: str) -> "Sana":
kun, oy, yil = map(int, s.split("."))
return cls(kun, oy, yil) # ⭐ cls, Sana emas
@classmethod
def bugun(cls) -> "Sana":
d = date.today()
return cls(d.day, d.month, d.year) Nega cls(), Sana() emas:
class UzbekSana(Sana):
def ozbekcha(self): ...
s = UzbekSana.satrdan("15.03.2026")
type(s) # UzbekSana ✅ — cls tufayli
s.ozbekcha() # ✅ ishlaydiAgar Sana(...) yozilganda — UzbekSana.satrdan() ham Sana qaytarardi.
Standart kutubxonadan:
dict.fromkeys(["a", "b"], 0)
int.from_bytes(b"\x01", "big")
datetime.now(), datetime.fromtimestamp(0), datetime.fromisoformat(...)
Decimal.from_float(0.1)
Path.cwd(), Path.home()
frozenset.fromkeys # yo'q, lekin naqsh bir xil2.3. Fabrika naqshlari
A) Turli formatlar:
@classmethod
def satrdan(cls, s): ...
@classmethod
def jsondan(cls, j): ...
@classmethod
def fayldan(cls, yol): ...Har birining nomi, hujjati va testi alohida.
B) Sukut konfiguratsiyalar:
@classmethod
def ishlab_chiqish(cls): return cls(debug=True, port=8000)
@classmethod
def ishlab_chiqarish(cls): return cls(debug=False, port=443)C) Nusxalash va o'zgartirish:
@classmethod
def nusxadan(cls, boshqa, **ozgarishlar):
m = {**boshqa.lugat(), **ozgarishlar}
return cls(**m)D) Registry / dispatcher:
@classmethod
def yarat(cls, tur: str, **kw):
Sinf = cls._royxat[tur]
return Sinf(**kw) Fabrika __init__ da isinstance shoxlanishi o'rniga:
# ⚠️ Yomon
def __init__(self, m):
if isinstance(m, str): ...
elif isinstance(m, dict): ...
elif isinstance(m, Path): ...
# ✅ Yaxshi
Sana.satrdan(...) Sana.lugatdan(...) Sana.fayldan(...)2.4. classmethod va sinf holati
class Hisoblagich:
_jami = 0
_kesh: dict = {}
@classmethod
def statistika(cls) -> dict:
return {"jami": cls._jami, "kesh": len(cls._kesh)}
@classmethod
def tozala(cls) -> None:
"""⭐ Testlar uchun."""
cls._jami = 0
cls._kesh.clear()Meros bilan ehtiyot:
class Ota:
_n = 0
@classmethod
def oshir(cls):
cls._n += 1 # ⚠️ AVLODGA yozadi
class Bola(Ota): pass
Bola.oshir()
Ota._n # 0 ⚠️
Bola._n # 1 ⚠️ yangi atributUmumiy hisoblagich kerak bo'lsa — aniq sinf:
@classmethod
def oshir(cls):
Ota._n += 1 # ✅ har doim Ota2.5. @staticmethod — qachon kerak
Uch to'g'ri holat:
# 1. Sinf bilan mantiqan bog'liq, lekin holatga bog'liq emas
class Sana:
@staticmethod
def kabisami(yil: int) -> bool:
return yil % 4 == 0 and (yil % 100 != 0 or yil % 400 == 0)
# 2. Nom fazosini tozalash (yordamchi funksiya)
class Parser:
@staticmethod
def _tokenla(s): ...
# 3. Avlodlar qayta aniqlashi mumkin
class Asos:
@staticmethod
def formatla(q): return str(q)
class Maxsus(Asos):
@staticmethod
def formatla(q): return f"[{q}]"Ortiqcha holatlar:
# 1. Modul funksiyasi bo'lishi kerak
class Utils:
@staticmethod
def satr_tozala(s): return s.strip() # ⚠️ modulga
# 2. cls kerak bo'lishi mumkin
class A:
@staticmethod
def yarat(): return A() # ⚠️ classmethod bo'lsin Test: metod self ham, cls ham ishlatmasa — u haqiqatan shu sinfga tegishlimi?
2.6. Ikkalasi ham deskriptor
class classmethod:
def __init__(self, f): self.f = f
def __get__(self, obj, ega=None):
if ega is None: ega = type(obj)
return MethodType(self.f, ega) # ⭐ SINFGA bog'lash
class staticmethod:
def __init__(self, f): self.f = f
def __get__(self, obj, ega=None):
return self.f # ⭐ bog'lamaydi Uchala metod turi — bir mexanizm, faqat __get__ farq qiladi:
| Deskriptor | __get__ qaytaradi |
|---|---|
function |
MethodType(f, obj) — nusxaga bog'langan |
classmethod |
MethodType(f, cls) — sinfga bog'langan |
staticmethod |
f — bog'lanmagan |
Turlarni ko'rish:
type(A.__dict__["statik"]) # <class 'staticmethod'>
type(A.statik) # <class 'function'> ⭐ __get__ dan keyin
type(A.__dict__["sinf"]) # <class 'classmethod'>
type(A.sinf) # <class 'method'>2.7. Kombinatsiyalar va cheklovlar
Python 3.9-3.10: classmethod + property:
class A:
@classmethod
@property
def x(cls): return "sinf property" # ⚠️ 3.9-3.10 da ishlardi 3.11 da olib tashlandi — chalkash va noto'g'ri ishlardi. Muqobil: metaklass yoki oddiy classmethod.
Ishlaydigan kombinatsiyalar:
class A:
@classmethod
@functools.cache # ✅ keshlangan fabrika
def yarat(cls, k): return cls(k)
@staticmethod
@functools.lru_cache(maxsize=128) # ✅
def hisobla(x): return x ** 2 Tartib muhim: @classmethod eng tashqarida bo'lsin.
super() bilan:
class Bola(Ota):
@classmethod
def yarat(cls):
return super().yarat() # ✅ ishlaydi (cls bor)
@staticmethod
def f():
return super().f() # ❌ RuntimeError
return super(Bola, Bola).f() # ✅ aniq shakl3. Tez ma'lumotnoma
Uch tur
def f(self) nusxa metod obj.f() / A.f(obj)
@classmethod
def f(cls) sinf metod A.f() / obj.f()
@staticmethod
def f() statik A.f() / obj.f()Fabrika naqshi
@classmethod
def satrdan(cls, s):
return cls(...) ⭐ cls, sinf nomi EMAS
Meros: UzbekSana.satrdan(...) → UzbekSana ✅Deskriptorlar
function.__get__ → MethodType(f, obj) nusxaga
classmethod.__get__ → MethodType(f, cls) sinfga
staticmethod.__get__ → f bog'lanmaganTuzoqlar
return Sana(...) ⚠️ meros buziladi
return cls(...) ✅
cls._n += 1 ⚠️ avlodga yangi atribut
Ota._n += 1 ✅ umumiy hisoblagich
@staticmethod + super() ❌ RuntimeError
@classmethod @property ❌ 3.11 dan olib tashlangan4. Batafsil misollar
Misol 1 — Uch tur va deskriptorlar
"""self, cls va hech narsa."""
from types import MethodType
print("=== 1. Uch turning farqi ===\n")
class Namoyish:
ATRIBUT = "sinf atributi"
def __init__(self, nom): self.nom = nom
def nusxa_metod(self):
return f"nusxa: self.nom={self.nom}"
@classmethod
def sinf_metod(cls):
return f"sinf: cls={cls.__name__}, cls.ATRIBUT={cls.ATRIBUT!r}"
@staticmethod
def statik_metod():
return "statik: kontekst yo'q"
n = Namoyish("obyekt")
print(f" Nusxadan chaqirish:")
for m in ["nusxa_metod", "sinf_metod", "statik_metod"]:
print(f" n.{m}()")
print(f" → {getattr(n, m)()}")
print(f"\n Sinfdan chaqirish:")
for kod, f in [
("Namoyish.nusxa_metod()", lambda: Namoyish.nusxa_metod()),
("Namoyish.nusxa_metod(n)", lambda: Namoyish.nusxa_metod(n)),
("Namoyish.sinf_metod()", lambda: Namoyish.sinf_metod()),
("Namoyish.statik_metod()", lambda: Namoyish.statik_metod()),
]:
try:
natija = f"✅ {f()}"
except TypeError as e:
natija = f"❌ TypeError: {e}"
print(f" {kod:<32} {natija}")
print("\n=== ⭐ 2. Deskriptor turlari ===\n")
print(f" {'Nom':<16} {'__dict__ da':<18} {'Sinfdan':<12} {'Nusxadan'}")
print(" " + "─" * 62)
for nom in ["nusxa_metod", "sinf_metod", "statik_metod"]:
xom = type(Namoyish.__dict__[nom]).__name__
sinfdan = type(getattr(Namoyish, nom)).__name__
nusxadan = type(getattr(n, nom)).__name__
print(f" {nom:<16} {xom:<18} {sinfdan:<12} {nusxadan}")
print(f"""
⭐ __get__ NIMA QAYTARADI:
function.__get__(obj, cls) → MethodType(f, obj) nusxaga
classmethod.__get__(obj, cls) → MethodType(f, cls) SINFGA
staticmethod.__get__(obj, cls) → f bog'lanmagan
""")
print(f" Qo'lda tekshirish:")
for nom in ["nusxa_metod", "sinf_metod", "statik_metod"]:
d = Namoyish.__dict__[nom]
olingan = d.__get__(n, Namoyish)
bogl = getattr(olingan, "__self__", "— (bog'lanmagan)")
if hasattr(bogl, "__name__"):
bogl = f"sinf: {bogl.__name__}"
elif bogl != "— (bog'lanmagan)":
bogl = f"nusxa: {bogl.nom}"
print(f" {nom:<16} __self__ = {bogl}")
print("\n=== ⭐ 3. Meros: cls haqiqiy sinfni biladi ===\n")
class Ota:
NOM = "Ota"
@classmethod
def sinf_metod(cls):
return f"cls={cls.__name__}, NOM={cls.NOM!r}"
@staticmethod
def statik_metod():
return f"Ota.NOM={Ota.NOM!r}" # ⚠️ qattiq yozilgan
def nusxa_metod(self):
return f"type(self)={type(self).__name__}"
class Bola(Ota):
NOM = "Bola"
class Nabira(Bola):
NOM = "Nabira"
print(f" {'Sinf':<10} {'sinf_metod()':<32} {'statik_metod()'}")
print(" " + "─" * 68)
for S in (Ota, Bola, Nabira):
print(f" {S.__name__:<10} {S.sinf_metod():<32} {S.statik_metod()}")
print(f"\n Nusxadan:")
for S in (Ota, Bola, Nabira):
o = S()
print(f" {S.__name__:<10} {o.sinf_metod():<32} {o.nusxa_metod()}")
print(f"""
⭐ cls — CHAQIRILGAN sinf, aniqlangan sinf emas.
Bola.sinf_metod() → cls = Bola
⚠️ statik_metod da Ota qattiq yozilgan — avlodda o'zgarmadi.
""")
print("=== ⭐ 4. Fabrika: cls vs sinf nomi ===\n")
class SanaYomon:
def __init__(self, kun, oy, yil):
self.kun, self.oy, self.yil = kun, oy, yil
@classmethod
def satrdan(cls, s):
kun, oy, yil = map(int, s.split("."))
return SanaYomon(kun, oy, yil) # ⚠️ qattiq yozilgan
def __repr__(self):
return f"{type(self).__name__}({self.kun}, {self.oy}, {self.yil})"
class SanaYaxshi:
def __init__(self, kun, oy, yil):
self.kun, self.oy, self.yil = kun, oy, yil
@classmethod
def satrdan(cls, s):
kun, oy, yil = map(int, s.split("."))
return cls(kun, oy, yil) # ⭐ cls
def __repr__(self):
return f"{type(self).__name__}({self.kun}, {self.oy}, {self.yil})"
class UzbekYomon(SanaYomon):
OYLAR = ("yanvar", "fevral", "mart")
def ozbekcha(self):
return f"{self.kun}-{self.OYLAR[self.oy - 1]}"
class UzbekYaxshi(SanaYaxshi):
OYLAR = ("yanvar", "fevral", "mart")
def ozbekcha(self):
return f"{self.kun}-{self.OYLAR[self.oy - 1]}"
for Sinf in (UzbekYomon, UzbekYaxshi):
s = Sinf.satrdan("15.03.2026")
print(f" {Sinf.__name__}.satrdan('15.03.2026')")
print(f" natija: {s!r}")
print(f" turi: {type(s).__name__}")
try:
print(f" ozbekcha(): {s.ozbekcha()!r} ✅")
except AttributeError as e:
print(f" ozbekcha(): ❌ AttributeError: {e}")
print()
print("=== ⚠️ 5. classmethod va sinf holati ===\n")
class Yomon:
_n = 0
@classmethod
def oshir(cls):
cls._n += 1 # ⚠️ AVLODGA yozadi
class YomonBola(Yomon): pass
class Yaxshi:
_n = 0
@classmethod
def oshir(cls):
Yaxshi._n += 1 # ✅ har doim Yaxshi
class YaxshiBola(Yaxshi): pass
Yomon.oshir(); YomonBola.oshir(); YomonBola.oshir()
Yaxshi.oshir(); YaxshiBola.oshir(); YaxshiBola.oshir()
print(f" Har biriga 3 marta oshir() (1 ota, 2 avlod):\n")
print(f" {'Yondashuv':<16} {'Ota._n':<10} {'Bola._n':<10} "
f"{'Bola.__dict__ da'}")
print(" " + "─" * 56)
print(f" {'cls._n += 1':<16} {Yomon._n:<10} {YomonBola._n:<10} "
f"{'_n' in YomonBola.__dict__}")
print(f" {'Yaxshi._n += 1':<16} {Yaxshi._n:<10} {YaxshiBola._n:<10} "
f"{'_n' in YaxshiBola.__dict__}")
print(f"""
⭐ SABAB: cls._n += 1 ≡ cls._n = cls._n + 1
1. O'QISH: cls._n → merosdan (Ota dan)
2. YOZISH: cls.__dict__["_n"] = ... ⚠️ AVLODGA
IKKALASI HAM to'g'ri bo'lishi mumkin:
cls._n += 1 → har avlod sinfga alohida hisoblagich
Ota._n += 1 → butun ierarxiya uchun bitta
""")
print("=== ⚠️ 6. staticmethod va super() ===\n")
class AsosS:
@staticmethod
def f(): return "AsosS.f"
@classmethod
def g(cls): return f"AsosS.g ({cls.__name__})"
class AvlodS(AsosS):
@staticmethod
def f_yomon():
try:
return super().f() # ❌
except RuntimeError as e:
return f"❌ RuntimeError: {str(e)[:40]}"
@staticmethod
def f_yaxshi():
return f"AvlodS → {super(AvlodS, AvlodS).f()}" # ✅
@classmethod
def g_yaxshi(cls):
return f"AvlodS → {super().g()}" # ✅ ishlaydi
print(f" @staticmethod da super():")
print(f" {AvlodS.f_yomon()}")
print(f" {AvlodS.f_yaxshi()} ✅ aniq shakl")
print(f"\n @classmethod da super():")
print(f" {AvlodS.g_yaxshi()} ✅ ishlaydi")
print(f"""
⭐ SABAB: super() ikki narsani izlaydi:
1. __class__ yopilmasi — ✅ bor (metod ichida)
2. co_varnames[0] — ⚠️ staticmethod da YO'Q
@classmethod da cls birinchi argument → ishlaydi
""")
print("=== 7. classmethod ni qo'lda yozish ===\n")
class MeningClassmethod:
"""classmethod ning sodda amalga oshirilishi."""
def __init__(self, f):
self.f = f
self.__doc__ = f.__doc__
self.__name__ = f.__name__
def __get__(self, obj, ega=None):
if ega is None:
ega = type(obj)
return MethodType(self.f, ega) # ⭐ SINFGA
class MeningStaticmethod:
def __init__(self, f):
self.f = f
self.__doc__ = f.__doc__
def __get__(self, obj, ega=None):
return self.f # ⭐ bog'lamaydi
class Sinov:
NOM = "Sinov"
@MeningClassmethod
def sinf(cls):
"""Sinf metodi."""
return f"cls={cls.__name__}, NOM={cls.NOM}"
@MeningStaticmethod
def statik(x):
"""Statik metod."""
return f"statik({x})"
class SinovBola(Sinov):
NOM = "SinovBola"
print(f" Sinov.sinf() = {Sinov.sinf()}")
print(f" SinovBola.sinf() = {SinovBola.sinf()} ⭐ cls to'g'ri")
print(f" Sinov().sinf() = {Sinov().sinf()}")
print(f" Sinov.statik(5) = {Sinov.statik(5)}")
print(f" Sinov().statik(5) = {Sinov().statik(5)}")
print(f"\n Turlar:")
print(f" type(Sinov.__dict__['sinf']) = "
f"{type(Sinov.__dict__['sinf']).__name__}")
print(f" type(Sinov.sinf) = {type(Sinov.sinf).__name__}")
print(f" Sinov.sinf.__self__ = {Sinov.sinf.__self__}")
print(f"""
⭐ Haqiqiy classmethod/staticmethod C da yozilgan,
lekin mantiq AYNAN shunday.
""")Natijaning muhim qismi:
=== ⭐ 2. Deskriptor turlari ===
Nom __dict__ da Sinfdan Nusxadan
──────────────────────────────────────────────────────────────
nusxa_metod function function method
sinf_metod classmethod method method
statik_metod staticmethod function function
=== ⭐ 3. Meros: cls haqiqiy sinfni biladi ===
Sinf sinf_metod() statik_metod()
────────────────────────────────────────────────────────────────────
Ota cls=Ota, NOM='Ota' Ota.NOM='Ota'
Bola cls=Bola, NOM='Bola' Ota.NOM='Ota'
Nabira cls=Nabira, NOM='Nabira' Ota.NOM='Ota'
=== ⭐ 4. Fabrika: cls vs sinf nomi ===
UzbekYomon.satrdan('15.03.2026')
turi: SanaYomon
ozbekcha(): ❌ AttributeError
UzbekYaxshi.satrdan('15.03.2026')
turi: UzbekYaxshi
ozbekcha(): '15-mart' ✅
=== ⚠️ 5. classmethod va sinf holati ===
Yondashuv Ota._n Bola._n Bola.__dict__ da
────────────────────────────────────────────────────────
cls._n += 1 1 3 True
Yaxshi._n += 1 3 3 FalseNima ko'rsatdi: 2.1, 2.2, 2.4, 2.6, 2.7-bo'limlar.
Misol 2 — Fabrika metodlari
"""@classmethod ning asosiy qo'llanishi."""
from __future__ import annotations
import json
import re
from dataclasses import dataclass, field, asdict
from datetime import date, datetime, timedelta
from pathlib import Path
print("=== 1. Turli formatlardan ===\n")
class Sana:
"""Ko'p fabrika metodi bilan sana."""
OYLAR = ("yanvar", "fevral", "mart", "aprel", "may", "iyun",
"iyul", "avgust", "sentabr", "oktabr", "noyabr", "dekabr")
KUNLAR = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
__slots__ = ("kun", "oy", "yil")
def __init__(self, kun: int, oy: int, yil: int):
if not 1 <= oy <= 12:
raise ValueError(f"Oy 1–12 oralig'ida: {oy}")
maks = self.KUNLAR[oy - 1] + (
1 if oy == 2 and self.kabisami(yil) else 0
)
if not 1 <= kun <= maks:
raise ValueError(f"{oy}-oyda {maks} kun bor: {kun}")
object.__setattr__(self, "kun", kun)
object.__setattr__(self, "oy", oy)
object.__setattr__(self, "yil", yil)
# ═══ FABRIKA METODLARI ═══
@classmethod
def bugun(cls) -> "Sana":
"""Bugungi sana."""
d = date.today()
return cls(d.day, d.month, d.year)
@classmethod
def izodan(cls, s: str) -> "Sana":
"""ISO 8601: '2026-03-15'."""
try:
yil, oy, kun = map(int, s.strip().split("-"))
except ValueError as e:
raise ValueError(f"ISO format 'YYYY-MM-DD': {s!r}") from e
return cls(kun, oy, yil)
@classmethod
def nuqtali(cls, s: str) -> "Sana":
"""'15.03.2026'."""
try:
kun, oy, yil = map(int, s.strip().split("."))
except ValueError as e:
raise ValueError(f"Format 'kk.oo.yyyy': {s!r}") from e
return cls(kun, oy, yil)
@classmethod
def ozbekcha(cls, s: str) -> "Sana":
"""'15-mart 2026' yoki '15 mart 2026'."""
m = re.match(r"^\s*(\d{1,2})\s*[-\s]\s*([^\s\d]+)\s+(\d{4})\s*$", s)
if not m:
raise ValueError(f"Format '15-mart 2026': {s!r}")
kun, oy_nom, yil = m.groups()
oy_nom = oy_nom.lower()
if oy_nom not in cls.OYLAR:
raise ValueError(f"Noma'lum oy: {oy_nom!r}")
return cls(int(kun), cls.OYLAR.index(oy_nom) + 1, int(yil))
@classmethod
def timestampdan(cls, ts: float) -> "Sana":
"""Unix vaqt tamg'asidan."""
d = datetime.fromtimestamp(ts)
return cls(d.day, d.month, d.year)
@classmethod
def kunlardan(cls, n: int, boshlanish: "Sana | None" = None) -> "Sana":
"""N kundan keyingi sana."""
b = boshlanish or cls.bugun()
d = date(b.yil, b.oy, b.kun) + timedelta(days=n)
return cls(d.day, d.month, d.year)
@classmethod
def avtomatik(cls, s: str) -> "Sana":
"""⭐ Formatni avtomatik aniqlaydi."""
s = s.strip()
for fabrika in (cls.izodan, cls.nuqtali, cls.ozbekcha):
try:
return fabrika(s)
except ValueError:
continue
raise ValueError(f"Sana formatini aniqlab bo'lmadi: {s!r}")
# ═══ STATIK YORDAMCHILAR ═══
@staticmethod
def kabisami(yil: int) -> bool:
"""⭐ Sinf va nusxa holatiga bog'liq EMAS."""
return yil % 4 == 0 and (yil % 100 != 0 or yil % 400 == 0)
@staticmethod
def oy_kunlari(oy: int, yil: int) -> int:
if oy == 2 and Sana.kabisami(yil):
return 29
return Sana.KUNLAR[oy - 1]
# ═══ NUSXA METODLARI ═══
def iso(self) -> str:
return f"{self.yil:04d}-{self.oy:02d}-{self.kun:02d}"
def ozbekcha_matn(self) -> str:
return f"{self.kun}-{self.OYLAR[self.oy - 1]} {self.yil}"
def __repr__(self):
return f"{type(self).__name__}({self.kun}, {self.oy}, {self.yil})"
def __eq__(self, b):
if not isinstance(b, Sana): return NotImplemented
return (self.yil, self.oy, self.kun) == (b.yil, b.oy, b.kun)
def __lt__(self, b):
if not isinstance(b, Sana): return NotImplemented
return (self.yil, self.oy, self.kun) < (b.yil, b.oy, b.kun)
def __hash__(self):
return hash((self.yil, self.oy, self.kun))
FABRIKALAR = [
("Sana(15, 3, 2026)", lambda: Sana(15, 3, 2026)),
("Sana.bugun()", lambda: Sana.bugun()),
("Sana.izodan('2026-03-15')", lambda: Sana.izodan("2026-03-15")),
("Sana.nuqtali('15.03.2026')", lambda: Sana.nuqtali("15.03.2026")),
("Sana.ozbekcha('15-mart 2026')", lambda: Sana.ozbekcha("15-mart 2026")),
("Sana.timestampdan(1773532800)", lambda: Sana.timestampdan(1773532800)),
("Sana.kunlardan(30, Sana(1,1,2026))",
lambda: Sana.kunlardan(30, Sana(1, 1, 2026))),
]
for kod, f in FABRIKALAR:
s = f()
print(f" {kod:<38} → {s!r}")
print(f" {'':<38} {s.ozbekcha_matn()}")
print("\n\n2. ⭐ Avtomatik aniqlash:\n")
SATRLAR = ["2026-03-15", "15.03.2026", "15-mart 2026", "15 mart 2026",
"noto'g'ri", "2026/03/15"]
for s in SATRLAR:
try:
natija = f"✅ {Sana.avtomatik(s)!r}"
except ValueError as e:
natija = f"❌ ValueError: {str(e)[:40]}"
print(f" {s!r:<20} {natija}")
print("\n\n3. Statik metodlar (obyektsiz):\n")
print(f" {'Yil':<8} {'Kabisami':<12} {'Fevral kunlari'}")
print(" " + "─" * 36)
for yil in [2023, 2024, 2025, 2000, 1900, 2100]:
print(f" {yil:<8} {Sana.kabisami(yil)!s:<12} "
f"{Sana.oy_kunlari(2, yil)}")
print(f"\n ⭐ Obyekt yaratmasdan ishlaydi:")
print(f" Sana.kabisami(2024) = {Sana.kabisami(2024)}")
print("\n\n=== ⭐ 4. Meros bilan ===\n")
class MilodiySana(Sana):
"""Qo'shimcha imkoniyatlar bilan."""
HAFTA = ("dushanba", "seshanba", "chorshanba", "payshanba",
"juma", "shanba", "yakshanba")
def hafta_kuni(self) -> str:
d = date(self.yil, self.oy, self.kun)
return self.HAFTA[d.weekday()]
def dam_olishmi(self) -> bool:
return self.hafta_kuni() in ("shanba", "yakshanba")
def __repr__(self):
return (f"MilodiySana({self.kun}, {self.oy}, {self.yil}, "
f"{self.hafta_kuni()})")
print(f" ⭐ BARCHA fabrika metodlari MilodiySana qaytaradi:\n")
for kod, f in [
("MilodiySana.izodan('2026-03-15')",
lambda: MilodiySana.izodan("2026-03-15")),
("MilodiySana.nuqtali('01.01.2026')",
lambda: MilodiySana.nuqtali("01.01.2026")),
("MilodiySana.ozbekcha('25-dekabr 2026')",
lambda: MilodiySana.ozbekcha("25-dekabr 2026")),
("MilodiySana.avtomatik('2026-07-04')",
lambda: MilodiySana.avtomatik("2026-07-04")),
("MilodiySana.kunlardan(7, MilodiySana(1,1,2026))",
lambda: MilodiySana.kunlardan(7, MilodiySana(1, 1, 2026))),
]:
s = f()
print(f" {kod}")
print(f" → {s!r}")
print(f" turi: {type(s).__name__}, dam olish: {s.dam_olishmi()}")
print(f"""
⭐ Bitta ham fabrika metodini QAYTA YOZISH kerak bo'lmadi.
cls(...) tufayli hammasi avtomatik ishlaydi.
""")
print("=== 5. Sukut konfiguratsiyalar ===\n")
@dataclass
class Sozlama:
host: str = "localhost"
port: int = 8000
debug: bool = True
ishchi: int = 1
vaqt_chegarasi: float = 30.0
jurnal: str = "debug"
# ═══ FABRIKA: tayyor konfiguratsiyalar ═══
# ⚠️ cls(port=8000, **ozgarishlar) YOZMANG: ishlab_chiqish(port=9000)
# → TypeError: got multiple values for keyword argument 'port'.
# Standart qiymatlarni lug'atda birlashtiring — o'ngdagisi yutadi.
@classmethod
def ishlab_chiqish(cls, **ozgarishlar) -> "Sozlama":
return cls(**{"host": "localhost", "port": 8000, "debug": True,
"ishchi": 1, "jurnal": "debug", **ozgarishlar})
@classmethod
def sinov(cls, **ozgarishlar) -> "Sozlama":
return cls(**{"host": "0.0.0.0", "port": 8001, "debug": True,
"ishchi": 2, "vaqt_chegarasi": 5.0, "jurnal": "info",
**ozgarishlar})
@classmethod
def ishlab_chiqarish(cls, **ozgarishlar) -> "Sozlama":
return cls(**{"host": "0.0.0.0", "port": 443, "debug": False,
"ishchi": 8, "vaqt_chegarasi": 60.0, "jurnal": "xato",
**ozgarishlar})
# ═══ FABRIKA: manbalardan ═══
@classmethod
def jsondan(cls, matn: str) -> "Sozlama":
m = json.loads(matn)
maydonlar = {f.name for f in cls.__dataclass_fields__.values()}
notogri = set(m) - maydonlar
if notogri:
raise ValueError(f"Noma'lum maydonlar: {sorted(notogri)}")
return cls(**m)
@classmethod
def muhitdan(cls, muhit: dict[str, str], prefiks="APP_") -> "Sozlama":
m = {}
for f in cls.__dataclass_fields__.values():
kalit = f"{prefiks}{f.name.upper()}"
if kalit not in muhit:
continue
xom = muhit[kalit]
if f.type is bool or f.type == "bool":
m[f.name] = xom.lower() in ("1", "true", "ha")
elif f.type is int or f.type == "int":
m[f.name] = int(xom)
elif f.type is float or f.type == "float":
m[f.name] = float(xom)
else:
m[f.name] = xom
return cls(**m)
# ═══ FABRIKA: nusxadan ═══
@classmethod
def nusxadan(cls, boshqa: "Sozlama", **ozgarishlar) -> "Sozlama":
"""⭐ Nusxa + o'zgarishlar."""
return cls(**{**asdict(boshqa), **ozgarishlar})
print(f" Tayyor konfiguratsiyalar:\n")
for nom in ["ishlab_chiqish", "sinov", "ishlab_chiqarish"]:
s = getattr(Sozlama, nom)()
print(f" {nom:<20} port={s.port:<6} debug={s.debug!s:<6} "
f"ishchi={s.ishchi} jurnal={s.jurnal}")
print(f"\n O'zgarishlar bilan:")
s = Sozlama.ishlab_chiqarish(port=8443, ishchi=16)
print(f" ishlab_chiqarish(port=8443, ishchi=16)")
print(f" → port={s.port}, ishchi={s.ishchi}, debug={s.debug}")
print(f"\n JSON dan:")
s2 = Sozlama.jsondan('{"host": "wisar.uz", "port": 443, "debug": false}')
print(f" {s2}")
try:
Sozlama.jsondan('{"xato_maydon": 1}')
except ValueError as e:
print(f" Noto'g'ri maydon → ✅ ValueError: {e}")
print(f"\n Muhitdan:")
MUHIT = {"APP_HOST": "api.wisar.uz", "APP_PORT": "3000",
"APP_DEBUG": "false", "APP_ISHCHI": "4"}
s3 = Sozlama.muhitdan(MUHIT)
print(f" {s3}")
print(f"\n Nusxadan:")
s4 = Sozlama.nusxadan(s3, port=9000, debug=True)
print(f" asl: port={s3.port}, debug={s3.debug}")
print(f" yangi: port={s4.port}, debug={s4.debug}")
print("\n\n=== 6. Registry fabrikasi ===\n")
class Format:
_royxat: dict[str, type["Format"]] = {}
def __init_subclass__(cls, /, nom: str = "", **kw):
super().__init_subclass__(**kw)
cls.nom = nom or cls.__name__.lower()
Format._royxat[cls.nom] = cls
@classmethod
def yarat(cls, nom: str, **kw) -> "Format":
"""⭐ Registry dispatcher."""
if nom not in cls._royxat:
raise KeyError(
f"Noma'lum format: {nom!r}. "
f"Mavjud: {sorted(cls._royxat)}"
)
return cls._royxat[nom](**kw)
@classmethod
def mavjudlar(cls) -> list[str]:
return sorted(cls._royxat)
def yoz(self, m) -> str:
raise NotImplementedError
class JsonFormat(Format, nom="json"):
def __init__(self, otstup=2): self.otstup = otstup
def yoz(self, m): return json.dumps(m, ensure_ascii=False,
indent=self.otstup)
class CsvFormat(Format, nom="csv"):
def __init__(self, ajratgich=","): self.ajratgich = ajratgich
def yoz(self, m):
if not m: return ""
kalitlar = list(m[0])
qatorlar = [self.ajratgich.join(kalitlar)]
for q in m:
qatorlar.append(self.ajratgich.join(str(q[k]) for k in kalitlar))
return "\n".join(qatorlar)
class MatnFormat(Format, nom="matn"):
def yoz(self, m):
return "\n".join(
" | ".join(f"{k}={v}" for k, v in q.items()) for q in m
)
MALUMOT = [{"ism": "Aziz", "yosh": 30}, {"ism": "Malika", "yosh": 25}]
print(f" Mavjud formatlar: {Format.mavjudlar()}\n")
for nom in Format.mavjudlar():
f = Format.yarat(nom)
natija = f.yoz(MALUMOT)
print(f" {nom}:")
for q in natija.split("\n")[:4]:
print(f" {q}")
print()
print(f" Argumentlar bilan:")
f = Format.yarat("csv", ajratgich=";")
print(f" Format.yarat('csv', ajratgich=';'):")
for q in f.yoz(MALUMOT).split("\n"):
print(f" {q}")
try:
Format.yarat("xml")
except KeyError as e:
print(f"\n Format.yarat('xml') → ✅ KeyError: {e.args[0]}")
print(f"""
⭐ FABRIKA NAQSHLARI XULOSASI:
1. Turli formatlar Sana.izodan, .nuqtali, .ozbekcha
2. Tayyor sozlamalar Sozlama.ishlab_chiqarish()
3. Manbalardan .jsondan(), .muhitdan(), .fayldan()
4. Nusxadan .nusxadan(asl, **ozgarishlar)
5. Registry Format.yarat("json")
6. Avtomatik aniqlash Sana.avtomatik()
⭐ HAMMASI cls() ISHLATADI → meros avtomatik ishlaydi
""")Natijaning muhim qismi:
=== 1. Turli formatlardan ===
Sana.ozbekcha('15-mart 2026') → Sana(15, 3, 2026)
15-mart 2026
Sana.kunlardan(30, Sana(1,1,2026)) → Sana(31, 1, 2026)
2. ⭐ Avtomatik aniqlash:
'2026-03-15' ✅ Sana(15, 3, 2026)
'15-mart 2026' ✅ Sana(15, 3, 2026)
"noto'g'ri" ❌ ValueError: Sana formatini aniqlab bo'lmadi
=== ⭐ 4. Meros bilan ===
MilodiySana.izodan('2026-03-15')
→ MilodiySana(15, 3, 2026, yakshanba)
turi: MilodiySana, dam olish: True
⭐ Bitta ham fabrika metodini QAYTA YOZISH kerak bo'lmadi.
=== 6. Registry fabrikasi ===
Mavjud formatlar: ['csv', 'json', 'matn']
Format.yarat('xml') → ✅ KeyError: Noma'lum format: 'xml'Nima ko'rsatdi: 2.2, 2.3-bo'limlar.
Misol 3 — @staticmethod — qachon kerak
"""Statik metod o'rinlimi — qaror qabul qilish."""
from __future__ import annotations
import math
import re
from functools import lru_cache
print("=== ✅ 1. Sinf mantiqiga tegishli yordamchi ===\n")
class Vaqt:
"""Statik metodlar sinf mantiqining bir qismi."""
def __init__(self, soat: int, daqiqa: int = 0, soniya: int = 0):
jami = self.jami_soniya(soat, daqiqa, soniya)
if not 0 <= jami < 86400:
raise ValueError(f"Vaqt 00:00:00–23:59:59 oralig'ida")
self.soat, self.daqiqa, self.soniya = soat, daqiqa, soniya
@staticmethod
def jami_soniya(soat: int, daqiqa: int, soniya: int) -> int:
"""⭐ Sof funksiya, lekin Vaqt mantiqi."""
return soat * 3600 + daqiqa * 60 + soniya
@staticmethod
def soniyadan_qismlar(n: int) -> tuple[int, int, int]:
"""⭐ Teskari amal."""
return n // 3600, (n % 3600) // 60, n % 60
@staticmethod
def yaroqlimi(soat: int, daqiqa: int, soniya: int) -> bool:
"""⭐ Obyekt YARATMASDAN tekshirish."""
return (0 <= soat < 24 and 0 <= daqiqa < 60
and 0 <= soniya < 60)
@classmethod
def soniyadan(cls, n: int) -> "Vaqt":
"""⭐ Fabrika — statik metodni ishlatadi."""
return cls(*cls.soniyadan_qismlar(n % 86400))
@classmethod
def satrdan(cls, s: str) -> "Vaqt":
qismlar = [int(q) for q in s.strip().split(":")]
while len(qismlar) < 3:
qismlar.append(0)
return cls(*qismlar[:3])
@property
def soniyalarda(self) -> int:
return self.jami_soniya(self.soat, self.daqiqa, self.soniya)
def __add__(self, b):
if isinstance(b, Vaqt):
return Vaqt.soniyadan(self.soniyalarda + b.soniyalarda)
if isinstance(b, int):
return Vaqt.soniyadan(self.soniyalarda + b)
return NotImplemented
def __repr__(self):
return f"Vaqt({self.soat}, {self.daqiqa}, {self.soniya})"
def __str__(self):
return f"{self.soat:02d}:{self.daqiqa:02d}:{self.soniya:02d}"
print(f" ⭐ Obyekt YARATMASDAN ishlatish:\n")
for kod, f in [
("Vaqt.jami_soniya(1, 30, 0)", lambda: Vaqt.jami_soniya(1, 30, 0)),
("Vaqt.soniyadan_qismlar(5400)", lambda: Vaqt.soniyadan_qismlar(5400)),
("Vaqt.yaroqlimi(25, 0, 0)", lambda: Vaqt.yaroqlimi(25, 0, 0)),
("Vaqt.yaroqlimi(14, 30, 0)", lambda: Vaqt.yaroqlimi(14, 30, 0)),
]:
print(f" {kod:<32} → {f()!r}")
print(f"\n Fabrika metodlari statikni ishlatadi:")
for kod, f in [
("Vaqt.soniyadan(5400)", lambda: Vaqt.soniyadan(5400)),
("Vaqt.satrdan('14:30')", lambda: Vaqt.satrdan("14:30")),
("Vaqt.satrdan('9')", lambda: Vaqt.satrdan("9")),
]:
v = f()
print(f" {kod:<26} → {v!r} = {v}")
print(f"\n Amallar:")
v = Vaqt(14, 30)
print(f" v = {v}")
print(f" v + Vaqt(1, 45) = {v + Vaqt(1, 45)}")
print(f" v + 3600 = {v + 3600}")
print(f"""
⭐ NEGA STATIK, MODUL FUNKSIYASI EMAS:
• jami_soniya Vaqt mantiqiga tegishli
• Vaqt.jami_soniya(...) — o'qiganda aniq
• Avlod sinf qayta aniqlashi mumkin
• Nom fazosi tozalanadi
""")
print("=== ⚠️ 2. Ortiqcha statik metodlar ===\n")
class UtilsYomon:
"""⚠️ Bu — sinf emas, modul bo'lishi kerak."""
@staticmethod
def satr_tozala(s): return s.strip()
@staticmethod
def royxat_tekisla(r): return [x for a in r for x in a]
@staticmethod
def lugat_birlashtir(a, b): return {**a, **b}
@staticmethod
def son_formatla(n): return f"{n:,}"
print(""" ⚠️ class UtilsYomon: — antipattern
• Nusxa yaratilmaydi
• self ham, cls ham ishlatilmaydi
• Metodlar bir-biriga bog'liq emas
• Bu — sinf emas, NOM FAZOSI
✅ To'g'ri yechim — modul:
# utils.py
def satr_tozala(s): return s.strip()
def royxat_tekisla(r): ...
# ishlatish:
import utils
utils.satr_tozala(s) ✅ bir xil nom fazosi
""")
print(f" ⭐ TEKSHIRUV SAVOLLARI:\n")
SAVOLLAR = [
("Sinf nusxasi yaratiladimi?", "Yo'q → modul"),
("Metodlar umumiy holatga tegadimi?", "Yo'q → modul"),
("Avlodlar qayta aniqlaydimi?", "Yo'q → modul"),
("Sinf nomi ma'no beradimi?", "Vaqt.jami_soniya ✅"),
("", "Utils.satr_tozala ⚠️"),
]
for savol, javob in SAVOLLAR:
print(f" {savol:<36} {javob}")
print("\n=== 3. Avlodlar qayta aniqlaydi ===\n")
class Hisobot:
"""⭐ Statik metod — kengaytirish nuqtasi."""
def __init__(self, malumot: list[dict]):
self.malumot = malumot
@staticmethod
def formatla_qiymat(q) -> str:
"""⭐ Avlodlar qayta aniqlashi mumkin."""
return str(q)
@staticmethod
def formatla_sarlavha(s: str) -> str:
return s.upper()
def chiqar(self) -> str:
if not self.malumot:
return "(bo'sh)"
kalitlar = list(self.malumot[0])
qatorlar = [" | ".join(self.formatla_sarlavha(k) for k in kalitlar)]
qatorlar.append("-" * len(qatorlar[0]))
for q in self.malumot:
qatorlar.append(
" | ".join(self.formatla_qiymat(q[k]) for k in kalitlar)
)
return "\n".join(qatorlar)
class PulHisobot(Hisobot):
@staticmethod
def formatla_qiymat(q) -> str:
if isinstance(q, (int, float)) and not isinstance(q, bool):
return f"{q:,.2f}"
return str(q)
class MarkdownHisobot(Hisobot):
@staticmethod
def formatla_sarlavha(s: str) -> str:
return f"**{s.title()}**"
@staticmethod
def formatla_qiymat(q) -> str:
return f"`{q}`"
MALUMOT = [
{"ism": "Aziz", "maosh": 8500000},
{"ism": "Malika", "maosh": 7000000},
]
for Sinf in (Hisobot, PulHisobot, MarkdownHisobot):
print(f" {Sinf.__name__}:")
for q in Sinf(MALUMOT).chiqar().split("\n"):
print(f" {q}")
print()
print(f""" ⭐ E'TIBOR: chiqar() self.formatla_qiymat(...) chaqiradi.
@staticmethod bo'lsa ham, self orqali chaqirilsa —
POLIMORFIZM ishlaydi (MRO bo'ylab qidiriladi).
⚠️ Hisobot.formatla_qiymat(...) yozilsa — qayta aniqlash
ISHLAMASDI.
""")
print("=== 4. staticmethod + keshlash ===\n")
class Matematika:
@staticmethod
@lru_cache(maxsize=256)
def fibonachchi(n: int) -> int:
"""⭐ Statik + keshlangan."""
if n < 2:
return n
return (Matematika.fibonachchi(n - 1)
+ Matematika.fibonachchi(n - 2))
@staticmethod
@lru_cache(maxsize=None)
def tubmi(n: int) -> bool:
if n < 2: return False
if n < 4: return True
if n % 2 == 0: return False
for i in range(3, int(math.isqrt(n)) + 1, 2):
if n % i == 0:
return False
return True
@classmethod
@lru_cache(maxsize=32)
def tublar(cls, chegara: int) -> tuple[int, ...]:
"""⭐ classmethod + kesh (cls hashable bo'lishi kerak)."""
return tuple(n for n in range(2, chegara) if cls.tubmi(n))
print(f" fibonachchi(50) = {Matematika.fibonachchi(50):,}")
print(f" Kesh: {Matematika.fibonachchi.cache_info()}")
print(f"\n tublar(50) = {Matematika.tublar(50)}")
print(f" tublar(50) (keshdan) = {Matematika.tublar(50)}")
print(f" Kesh: {Matematika.tublar.cache_info()}")
print(f"""
⚠️ DEKORATOR TARTIBI:
@staticmethod ⭐ ENG TASHQARIDA
@lru_cache
def f(...): ... ✅
@lru_cache
@staticmethod ⚠️ 3.10 gacha xato
def f(...): ...
⭐ 3.10+ da staticmethod chaqiriladigan bo'ldi,
lekin tartibni to'g'ri saqlash yaxshiroq.
""")
print("=== ⚠️ 5. classmethod + property (3.11 da olib tashlandi) ===\n")
import sys
print(f" Python versiyasi: {sys.version_info.major}."
f"{sys.version_info.minor}\n")
print(""" Python 3.9-3.10 da ishlardi:
class A:
@classmethod
@property
def x(cls): return "sinf property"
A.x # 'sinf property'
⚠️ 3.11 da OLIB TASHLANDI. Sabablari:
• Meros bilan noto'g'ri ishlardi
• help() va inspect buzilardi
• Deskriptor zanjirlanishi chalkash edi
✅ MUQOBILLAR:
1. Oddiy classmethod:
@classmethod
def x(cls): return "..."
A.x() # qavs bilan
2. Metaklass:
class Meta(type):
@property
def x(cls): return "..."
class A(metaclass=Meta): pass
A.x # ✅ qavssiz
3. Modul darajasidagi konstanta
""")
class Meta(type):
@property
def tavsif(cls):
return f"{cls.__name__} sinfi ({len(cls.__mro__)} daraja)"
class BilanMeta(metaclass=Meta):
pass
class AvlodMeta(BilanMeta):
pass
print(f" Metaklass bilan:")
print(f" BilanMeta.tavsif = {BilanMeta.tavsif!r}")
print(f" AvlodMeta.tavsif = {AvlodMeta.tavsif!r}")
print(f" ⚠️ Nusxadan ishlamaydi: ", end="")
try:
BilanMeta().tavsif
print("o'tdi")
except AttributeError:
print("❌ AttributeError")
print("\n=== 6. Qaror jadvali ===\n")
print("""
┌────────────────────────────────┬──────────────────────┐
│ Metod nima ishlatadi │ Tanlov │
├────────────────────────────────┼──────────────────────┤
│ self.atribut │ nusxa metod │
│ cls(...) qaytaradi │ ⭐ @classmethod │
│ cls.SINF_ATRIBUTI │ @classmethod │
│ Sinf holatini o'zgartiradi │ @classmethod │
│ Hech narsa (sof funksiya) │ @staticmethod │
│ Faqat argumentlar │ @staticmethod │
│ Umuman sinfga tegishli emas │ ❌ modul funksiyasi │
└────────────────────────────────┴──────────────────────┘
⭐ AMALIY TARTIB:
1. self kerakmi? → ha → nusxa metod
2. cls kerakmi? → ha → @classmethod
3. Sinf nomi ma'noli mi? → ha → @staticmethod
→ yo'q → modul funksiyasi
""")Natijaning muhim qismi:
=== ✅ 1. Sinf mantiqiga tegishli yordamchi ===
Vaqt.jami_soniya(1, 30, 0) → 5400
Vaqt.yaroqlimi(25, 0, 0) → False
Fabrika metodlari statikni ishlatadi:
Vaqt.soniyadan(5400) → Vaqt(1, 30, 0) = 01:30:00
=== 3. Avlodlar qayta aniqlaydi ===
Hisobot:
ISM | MAOSH
Aziz | 8500000
PulHisobot:
Aziz | 8,500,000.00
MarkdownHisobot:
**Ism** | **Maosh**
`Aziz` | `8500000`
=== 4. staticmethod + keshlash ===
fibonachchi(50) = 12,586,269,025
Kesh: CacheInfo(hits=48, misses=51, maxsize=256, currsize=51)Nima ko'rsatdi: 2.5, 2.7-bo'limlar.
Misol 4 — Amaliy: plagin tizimi
"""classmethod va staticmethod bilan to'liq arxitektura."""
from __future__ import annotations
import json
import re
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from datetime import datetime
from pathlib import Path
from typing import Any, ClassVar
print("=== MA'LUMOT IMPORTCHISI ===\n")
@dataclass
class Yozuv:
"""Bitta ma'lumot yozuvi."""
malumot: dict[str, Any]
manba: str = ""
qator: int = 0
def __getitem__(self, k): return self.malumot[k]
def __contains__(self, k): return k in self.malumot
def keys(self): return self.malumot.keys()
def __repr__(self):
return f"Yozuv({self.malumot!r}, {self.manba!r}:{self.qator})"
class ImportXatosi(Exception):
"""Import paytidagi xato."""
def __init__(self, xabar: str, qator: int = 0, manba: str = ""):
self.qator, self.manba = qator, manba
joy = f" ({manba}:{qator})" if manba else f" (qator {qator})"
super().__init__(f"{xabar}{joy}" if qator else xabar)
class Importchi(ABC):
"""Ma'lumot importi uchun asos.
⭐ __init_subclass__ avlodlarni AVTOMATIK ro'yxatga oladi.
"""
# ── Sinf atributlari (avlodlar qayta aniqlaydi) ──
KENGAYTMALAR: ClassVar[tuple[str, ...]] = ()
NOM: ClassVar[str] = ""
TAVSIF: ClassVar[str] = ""
# ── Umumiy registry ──
_royxat: ClassVar[dict[str, type["Importchi"]]] = {}
_kengaytma_xarita: ClassVar[dict[str, type["Importchi"]]] = {}
def __init_subclass__(cls, **kw):
super().__init_subclass__(**kw)
if not cls.NOM:
cls.NOM = cls.__name__.replace("Importchi", "").lower()
Importchi._royxat[cls.NOM] = cls
for k in cls.KENGAYTMALAR:
Importchi._kengaytma_xarita[k.lower()] = cls
# ═══ ABSTRAKT ═══
@abstractmethod
def tahlil(self, matn: str) -> list[Yozuv]:
"""Matnni yozuvlarga ajratadi."""
# ═══ CLASSMETHOD: fabrikalar ═══
@classmethod
def nomdan(cls, nom: str, **kw) -> "Importchi":
"""Nom bo'yicha importchi yaratadi."""
nom = nom.lower()
if nom not in cls._royxat:
raise KeyError(
f"Noma'lum importchi: {nom!r}. "
f"Mavjud: {sorted(cls._royxat)}"
)
return cls._royxat[nom](**kw)
@classmethod
def kengaytmadan(cls, yol: str | Path, **kw) -> "Importchi":
"""⭐ Fayl kengaytmasi bo'yicha."""
k = Path(yol).suffix.lower()
if k not in cls._kengaytma_xarita:
raise KeyError(
f"Kengaytma qo'llab-quvvatlanmaydi: {k!r}. "
f"Mavjud: {sorted(cls._kengaytma_xarita)}"
)
return cls._kengaytma_xarita[k](**kw)
@classmethod
def avtomatik(cls, matn: str, **kw) -> "Importchi":
"""⭐ Mazmunni tahlil qilib formatni aniqlaydi."""
for Sinf in cls._royxat.values():
if Sinf.taniydimi(matn):
return Sinf(**kw)
raise ValueError("Formatni aniqlab bo'lmadi")
@classmethod
def mavjudlar(cls) -> list[tuple[str, str, tuple[str, ...]]]:
return sorted(
(S.NOM, S.TAVSIF, S.KENGAYTMALAR)
for S in cls._royxat.values()
)
# ═══ STATICMETHOD: yordamchilar ═══
@staticmethod
def taniydimi(matn: str) -> bool:
"""⭐ Avlodlar qayta aniqlaydi."""
return False
@staticmethod
def _tozala(q: str) -> str:
"""⭐ Umumiy tozalash — barcha avlodlar ishlatadi."""
return q.strip().strip('"').strip("'")
@staticmethod
def _turga_ogir(q: str) -> Any:
"""⭐ Satrni mos turga o'giradi."""
q = q.strip()
if not q or q.lower() in ("null", "none", "nan"):
return None
if q.lower() in ("true", "ha", "yes"):
return True
if q.lower() in ("false", "yo'q", "no"):
return False
if re.fullmatch(r"-?\d+", q):
return int(q)
if re.fullmatch(r"-?\d*\.\d+([eE][-+]?\d+)?", q):
return float(q)
if re.fullmatch(r"\d{4}-\d{2}-\d{2}", q):
try:
return datetime.strptime(q, "%Y-%m-%d").date()
except ValueError:
pass
return q
# ═══ NUSXA METODLARI ═══
def __init__(self, *, turga_ogir: bool = True,
chegara: int | None = None):
self.turga_ogir = turga_ogir
self.chegara = chegara
self.xatolar: list[ImportXatosi] = []
def yukla(self, matn: str, manba: str = "") -> list[Yozuv]:
"""⭐ Umumiy quvur — avlodlar tahlil() ni beradi."""
self.xatolar.clear()
yozuvlar = self.tahlil(matn)
for i, y in enumerate(yozuvlar, 1):
y.manba = manba or self.NOM
y.qator = y.qator or i
if self.turga_ogir:
y.malumot = {
k: self._turga_ogir(v) if isinstance(v, str) else v
for k, v in y.malumot.items()
}
if self.chegara:
yozuvlar = yozuvlar[:self.chegara]
return yozuvlar
def __repr__(self):
return (f"{type(self).__name__}(turga_ogir={self.turga_ogir}, "
f"chegara={self.chegara})")
# ═══ AVLODLAR ═══
class CsvImportchi(Importchi):
KENGAYTMALAR = (".csv", ".tsv")
NOM = "csv"
TAVSIF = "Vergul bilan ajratilgan qiymatlar"
def __init__(self, *, ajratgich: str = ",", **kw):
super().__init__(**kw)
self.ajratgich = ajratgich
@staticmethod
def taniydimi(matn: str) -> bool:
qatorlar = matn.strip().split("\n")
if len(qatorlar) < 2:
return False
n = qatorlar[0].count(",")
return n > 0 and all(q.count(",") == n for q in qatorlar[:5])
def tahlil(self, matn: str) -> list[Yozuv]:
qatorlar = [q for q in matn.strip().split("\n") if q.strip()]
if not qatorlar:
return []
sarlavhalar = [self._tozala(k)
for k in qatorlar[0].split(self.ajratgich)]
natija = []
for i, q in enumerate(qatorlar[1:], 2):
qiymatlar = [self._tozala(v) for v in q.split(self.ajratgich)]
if len(qiymatlar) != len(sarlavhalar):
self.xatolar.append(ImportXatosi(
f"{len(sarlavhalar)} ustun kutildi, "
f"{len(qiymatlar)} keldi", i, self.NOM
))
continue
natija.append(Yozuv(dict(zip(sarlavhalar, qiymatlar)),
qator=i))
return natija
class JsonImportchi(Importchi):
KENGAYTMALAR = (".json",)
NOM = "json"
TAVSIF = "JSON massiv yoki obyekt"
@staticmethod
def taniydimi(matn: str) -> bool:
s = matn.strip()
return bool(s) and s[0] in "[{"
def tahlil(self, matn: str) -> list[Yozuv]:
try:
m = json.loads(matn)
except json.JSONDecodeError as e:
raise ImportXatosi(f"JSON xatosi: {e.msg}", e.lineno,
self.NOM) from e
if isinstance(m, dict):
m = [m]
if not isinstance(m, list):
raise ImportXatosi("JSON massiv yoki obyekt bo'lsin")
return [Yozuv(q if isinstance(q, dict) else {"qiymat": q},
qator=i)
for i, q in enumerate(m, 1)]
class KalitQiymatImportchi(Importchi):
KENGAYTMALAR = (".env", ".properties", ".ini")
NOM = "kalit-qiymat"
TAVSIF = "kalit=qiymat qatorlari"
@staticmethod
def taniydimi(matn: str) -> bool:
qatorlar = [q for q in matn.strip().split("\n")
if q.strip() and not q.strip().startswith("#")]
return bool(qatorlar) and all("=" in q for q in qatorlar[:5])
def tahlil(self, matn: str) -> list[Yozuv]:
m = {}
for i, q in enumerate(matn.strip().split("\n"), 1):
q = q.strip()
if not q or q.startswith("#"):
continue
if "=" not in q:
self.xatolar.append(
ImportXatosi(f"'=' topilmadi: {q!r}", i, self.NOM)
)
continue
k, _, v = q.partition("=")
m[self._tozala(k)] = self._tozala(v)
return [Yozuv(m, qator=1)] if m else []
print("1. ⭐ Avtomatik ro'yxat:\n")
print(f" {'Nom':<16} {'Kengaytmalar':<28} {'Tavsif'}")
print(" " + "─" * 76)
for nom, tavsif, kengaytmalar in Importchi.mavjudlar():
print(f" {nom:<16} {str(kengaytmalar):<28} {tavsif}")
print("\n\n2. Fabrika metodlari:\n")
MISOLLAR = {
"csv": "ism,yosh,faol\nAziz,30,true\nMalika,25,false",
"json": '[{"ism": "Bobur", "yosh": 40}, {"ism": "Dilnoza"}]',
"kalit-qiymat": "# Izoh\nHOST=localhost\nPORT=8000\nDEBUG=true",
}
print(f" a) Nom bo'yicha:")
for nom, matn in MISOLLAR.items():
imp = Importchi.nomdan(nom)
yozuvlar = imp.yukla(matn, manba=f"test.{nom}")
print(f" Importchi.nomdan({nom!r}) → {type(imp).__name__}")
for y in yozuvlar[:2]:
print(f" {y.malumot}")
print(f"\n b) Kengaytma bo'yicha:")
for yol in ["malumot.csv", "sozlama.json", ".env", "fayl.xml"]:
try:
imp = Importchi.kengaytmadan(yol)
n = f"✅ {type(imp).__name__}"
except KeyError as e:
n = f"❌ KeyError"
print(f" {yol:<18} → {n}")
print(f"\n c) ⭐ Avtomatik aniqlash:")
for nom, matn in MISOLLAR.items():
imp = Importchi.avtomatik(matn)
belgi = "✅" if imp.NOM == nom else "❌"
print(f" {nom:<16} → {type(imp).__name__:<26} {belgi}")
try:
Importchi.avtomatik("<xml>...</xml>")
except ValueError as e:
print(f" {'<xml>':<16} → ❌ ValueError: {e}")
print("\n\n3. ⭐ Statik metodlar — tur o'girish:\n")
QIYMATLAR = ["42", "-17", "3.14", "1e5", "true", "ha", "false",
"null", "", "2026-03-15", "matn", " probel "]
print(f" {'Kirish':<16} {'Natija':<24} {'Tur'}")
print(" " + "─" * 52)
for q in QIYMATLAR:
n = Importchi._turga_ogir(q)
print(f" {q!r:<16} {n!r:<24} {type(n).__name__}")
print("\n\n4. Tur o'girish yoqilgan/o'chirilgan:\n")
CSV = "ism,yosh,maosh,faol,sana\nAziz,30,8500000.50,true,2026-03-15"
for yoqilgan in (True, False):
imp = Importchi.nomdan("csv", turga_ogir=yoqilgan)
y = imp.yukla(CSV)[0]
print(f" turga_ogir={yoqilgan}:")
for k, v in y.malumot.items():
print(f" {k:<10} {v!r:<20} {type(v).__name__}")
print()
print("5. Xatolar bilan ishlash:\n")
BUZILGAN_CSV = ("ism,yosh,shahar\n"
"Aziz,30,Toshkent\n"
"Malika,25\n"
"Bobur,40,Samarqand,ortiqcha\n"
"Dilnoza,35,Buxoro")
imp = Importchi.nomdan("csv")
yozuvlar = imp.yukla(BUZILGAN_CSV, manba="xodimlar.csv")
print(f" Yuklandi: {len(yozuvlar)} yozuv")
for y in yozuvlar:
print(f" {y.qator}: {y.malumot}")
print(f"\n Xatolar: {len(imp.xatolar)}")
for x in imp.xatolar:
print(f" ❌ {x}")
print(f"\n Buzilgan JSON:")
try:
Importchi.nomdan("json").yukla("{buzilgan}", manba="a.json")
except ImportXatosi as e:
print(f" ❌ {e}")
print("\n\n6. Chegara va sozlamalar:\n")
KATTA_CSV = "n,kvadrat\n" + "\n".join(f"{i},{i*i}" for i in range(1, 21))
for chegara in [None, 3, 5]:
imp = Importchi.nomdan("csv", chegara=chegara)
y = imp.yukla(KATTA_CSV)
print(f" chegara={str(chegara):<6} → {len(y)} yozuv, "
f"oxirgisi: {y[-1].malumot if y else '—'}")
print(f"\n TSV (ajratgich=tab):")
TSV = "ism\tyosh\nAziz\t30"
imp = Importchi.nomdan("csv", ajratgich="\t")
print(f" {imp.yukla(TSV)[0].malumot}")
print("\n\n7. Yangi importchi qo'shish:\n")
class XmlImportchi(Importchi):
"""⭐ Mavjud kodni O'ZGARTIRMASDAN qo'shildi."""
KENGAYTMALAR = (".xml",)
NOM = "xml"
TAVSIF = "Sodda XML (bir daraja)"
@staticmethod
def taniydimi(matn: str) -> bool:
return matn.strip().startswith("<")
def tahlil(self, matn: str) -> list[Yozuv]:
natija = []
for i, blok in enumerate(
re.findall(r"<yozuv>(.*?)</yozuv>", matn, re.S), 1
):
m = {}
for teg, qiymat in re.findall(r"<(\w+)>([^<]*)</\1>", blok):
m[teg] = self._tozala(qiymat)
if m:
natija.append(Yozuv(m, qator=i))
return natija
XML = """
<malumot>
<yozuv><ism>Sardor</ism><yosh>28</yosh></yozuv>
<yozuv><ism>Nilufar</ism><yosh>45</yosh></yozuv>
</malumot>
"""
print(f" Yangi ro'yxat: {[n for n, _, _ in Importchi.mavjudlar()]}\n")
for kod, f in [
("Importchi.nomdan('xml')", lambda: Importchi.nomdan("xml")),
("Importchi.kengaytmadan('a.xml')", lambda: Importchi.kengaytmadan("a.xml")),
("Importchi.avtomatik(XML)", lambda: Importchi.avtomatik(XML)),
]:
imp = f()
print(f" {kod:<36} → {type(imp).__name__}")
print(f"\n Natija:")
for y in Importchi.avtomatik(XML).yukla(XML, manba="a.xml"):
print(f" {y}")
print(f"""
⭐ BU ARXITEKTURADA:
@classmethod — FABRIKALAR:
nomdan() registry bo'yicha
kengaytmadan() fayl turi bo'yicha
avtomatik() mazmun tahlili bo'yicha
mavjudlar() introspeksiya
@staticmethod — YORDAMCHILAR:
taniydimi() ⭐ avlodlar qayta aniqlaydi
_tozala() umumiy, holatga bog'liq emas
_turga_ogir() sof funksiya
__init_subclass__:
Avlodlarni AVTOMATIK ro'yxatga oladi
NOM va KENGAYTMALAR ni bog'laydi
⭐ YANGI FORMAT QO'SHISH:
• Sinf yozasiz
• KENGAYTMALAR, NOM, TAVSIF beradi
• tahlil() va taniydimi() ni yozadi
• ⭐ MAVJUD KOD O'ZGARMAYDI
""")Natijaning muhim qismi:
1. ⭐ Avtomatik ro'yxat:
Nom Kengaytmalar Tavsif
────────────────────────────────────────────────────────────────────────────
csv ('.csv', '.tsv') Vergul bilan ajratilgan
json ('.json',) JSON massiv yoki obyekt
kalit-qiymat ('.env', '.properties',...) kalit=qiymat qatorlari
2. Fabrika metodlari:
c) ⭐ Avtomatik aniqlash:
csv → CsvImportchi ✅
json → JsonImportchi ✅
kalit-qiymat → KalitQiymatImportchi ✅
3. ⭐ Statik metodlar — tur o'girish:
'42' 42 int
'true' True bool
'2026-03-15' datetime.date(2026, 3, 15) date
'null' None NoneType
5. Xatolar bilan ishlash:
Yuklandi: 2 yozuv
Xatolar: 2
❌ 3 ustun kutildi, 2 keldi (csv:3)Nima ko'rsatdi: 2.2, 2.3, 2.4, 2.5-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"cls — aniqlangan sinf" |
Chaqirilgan sinf |
"@staticmethod va modul funksiyasi bir xil" |
Nom fazosi va meros farqi bor |
"Fabrikada Sinf(...) yozsa bo'ladi" |
cls(...) — meros uchun |
"cls._n += 1 umumiy hisoblagichni oshiradi" |
Avlodga yangi atribut |
"@staticmethod da super() ishlaydi" |
RuntimeError |
"@classmethod @property ishlaydi" |
3.11 da olib tashlangan |
"A.statik — staticmethod obyekti" |
function (__get__ dan keyin) |
"@staticmethod polimorfizm bermaydi" |
self.f() orqali chaqirilsa — beradi |
6. Keng tarqalgan xatolar va yechimlari
1. Fabrikada sinf nomini qattiq yozish
@classmethod
def satrdan(cls, s):
return Sana(...) # ⚠️ meros buziladi
return cls(...) # ✅2. cls._n += 1 bilan hisoblagich
@classmethod
def oshir(cls): cls._n += 1 # ⚠️ avlodga
def oshir(cls): Ota._n += 1 # ✅ umumiy3. @staticmethod o'rniga @classmethod kerak
@staticmethod
def yarat(): return A() # ⚠️
@classmethod
def yarat(cls): return cls() # ✅4. Utils sinfi
class Utils: # ⚠️ modul bo'lsin
@staticmethod
def f(x): ...5. @staticmethod da super()
@staticmethod
def f(): return super().g() # ❌
def f(): return super(B, B).g() # ✅6. Dekorator tartibi
@lru_cache
@classmethod # ⚠️
def f(cls): ...
@classmethod # ✅ tashqarida
@lru_cache
def f(cls): ...7. __init__ da isinstance shoxlanishi
def __init__(self, m):
if isinstance(m, str): ... # ⚠️
Sana.satrdan(...) # ✅ fabrika8. Statik metodni sinf nomi bilan chaqirish
def f(self):
return Asos.formatla(x) # ⚠️ qayta aniqlash ishlamaydi
return self.formatla(x) # ✅ polimorfizm7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8.3-dars (o'tilgan): fabrika metodlari kirish
- 8.5-dars: sinf atributlari va hisoblagichlar
- 8.15-dars: deskriptorlar — ikkalasi ham deskriptor
- 8.17-dars:
dataclassva fabrika metodlari - 8.18-dars: ABC va
__init_subclass__ datetime,Path,dict,int— standart kutubxonadagi fabrikalarfunctools.lru_cache,singledispatchmethod
8. Eng yaxshi amaliyotlar
Fabrikada
cls()yozing. Sinf nomini qattiq yozmang.__init__— bitta yo'l, qolgani@classmethod.isinstanceshoxlanishi emas.Fabrika nomi aniq bo'lsin.
satrdan,jsondan,fayldan.Sinf hisoblagichida aniq sinf.
Ota._n += 1,cls._n += 1emas.@staticmethod— faqat sinfga tegishli bo'lsa. Aks holda modul.Statik metodni
self.f()bilan chaqiring. Polimorfizm saqlansin.@classmethodeng tashqi dekorator.lru_cachebilan.Tayyor konfiguratsiyalar — fabrika.
Sozlama.ishlab_chiqarish().
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
1. class A:
@classmethod
def f(cls): return cls.__name__
class B(A): pass
print(A.f(), B.f(), B().f())
2. class A:
@staticmethod
def f(): return "s"
print(A.f(), A().f())
3. class A:
@classmethod
def yarat(cls): return cls()
class B(A): pass
print(type(B.yarat()).__name__)
4. class A:
@classmethod
def yarat(cls): return A()
class B(A): pass
print(type(B.yarat()).__name__)
5. class A:
_n = 0
@classmethod
def f(cls): cls._n += 1
class B(A): pass
B.f(); B.f()
print(A._n, B._n)
6. class A:
@staticmethod
def f(): return 1
print(type(A.__dict__["f"]).__name__, type(A.f).__name__)
7. class A:
@classmethod
def f(cls): return 1
print(type(A.__dict__["f"]).__name__, type(A.f).__name__)
8. class A:
def f(self): return self.g()
@staticmethod
def g(): return "A"
class B(A):
@staticmethod
def g(): return "B"
print(B().f())
9. class A:
@classmethod
def f(cls): return cls
print(A.f() is A, A().f() is A)
10. class A:
@staticmethod
def f(x): return x * 2
print(A.f(3), A().f(3))
11. class A:
x = 1
@classmethod
def f(cls): return cls.x
class B(A): x = 2
print(A.f(), B.f())
12. print(dict.fromkeys("ab", 0), type(dict.fromkeys("ab")))Javoblar
A B Bs sBA— qattiq yozilgan0 2—B.__dict__gastaticmethod functionclassmethod methodB—self.g()orqali polimorfizmTrue True6 61 2{'a': 0, 'b': 0} <class 'dict'>
Vazifa 2: Xatolarni tuzating
1. @classmethod
def satrdan(cls, s): return Sana(...)
2. @staticmethod
def yarat(): return A()
3. @classmethod
def oshir(cls): cls._jami += 1 # umumiy kerak
4. class Utils:
@staticmethod
def tozala(s): return s.strip()
5. @staticmethod
def f(): return super().g()
6. @lru_cache
@classmethod
def f(cls, n): ...
7. def __init__(self, m):
if isinstance(m, str): ...
elif isinstance(m, dict): ...
8. def chiqar(self): return Asos.formatla(self.x)Javoblar
1. return cls(...)
2. @classmethod def yarat(cls): return cls()
3. Sinf._jami += 1 (aniq sinf nomi)
4. Modul funksiyalari qiling
5. return super(B, B).g()
6. @classmethod ni tashqariga
7. Fabrika metodlari: A.satrdan(), A.lugatdan()
8. return self.formatla(self.x)Vazifa 3: Rang sinfi
Yozing:
__init__(self, r, g, b)— 0-255 tekshiruv@classmethod hexdan("#ff5733")@classmethod hsldan(h, s, l)@classmethod nomdan("qizil")@classmethod tasodifiy()@staticmethod hex_yaroqlimi(s)- Avlod
RgbaRangda hammasi ishlasin
Vazifa 4: Fabrika tekshiruvchisi
Vosita yozing:
@classmethodlarni topsincls(...)o'rniga sinf nomi ishlatilganini@staticmethoddaclskerakligini (obyekt qaytaradi)cls._atr +=naqshini (ehtimoliy xato)Utilskabi sinflarni (faqat statik metodlar)- Har biri uchun tuzatish
Vazifa 5: Singleton fabrikasi
@classmethod nusxa()— har sinf uchun bitta- Meros bilan to'g'ri ishlasin (har avlodga o'ziniki)
tozala()— testlar uchun- Thread-safe variant
- Argumentlar bilan keshlash (
lru_cache) __new__bilan solishtiring
Vazifa 6: Ma'lumot modeli
Modelasos sinfi@classmethod lugatdan(),jsondan(),royxatdan()@classmethod maydonlar()— introspeksiya@staticmethod tekshir()— avlodlar qayta aniqlaydi__init_subclass__bilan registry- Meros bilan hammasi ishlasin
Vazifa 7: O'ylash
Nega Pythonda @classmethod bor — Java va C# da faqat static metodlar bo'lsa ham?
Javob
Chunki Pythonda sinf — birinchi darajali obyekt, va cls merosda to'g'ri ishlaydigan fabrika metodlarini mumkin qiladi.
1. Java dagi muammo
class Sana {
static Sana satrdan(String s) {
return new Sana(...); // ⚠️ Sana qattiq yozilgan
}
}
class UzbekSana extends Sana { }
Sana s = UzbekSana.satrdan("15.03.2026");
// ⚠️ Natija — Sana, UzbekSana emas Java da static metod sinfni bilmaydi:
thisyo'q- Sinfni dinamik aniqlab bo'lmaydi
- Meros bilan ishlamaydi
Java ning yechimlari:
// 1. Har avlodda qayta yozish (⚠️ takrorlanish)
class UzbekSana extends Sana {
static UzbekSana satrdan(String s) {
return new UzbekSana(...);
}
}
// 2. Refleksiya (⚠️ murakkab va sekin)
static <T extends Sana> T satrdan(Class<T> cls, String s) {
return cls.getConstructor(...).newInstance(...);
}
// 3. Abstract Factory naqshi (⚠️ ko'p kod)
interface SanaFabrika { Sana yarat(int k, int o, int y); }Design Patterns kitobidagi "Factory Method" naqshi — aynan shu muammoni hal qilish uchun o'ylab topilgan.
2. Pythonning yechimi
class Sana:
@classmethod
def satrdan(cls, s):
return cls(...) # ⭐ cls — haqiqiy sinf
class UzbekSana(Sana): pass
type(UzbekSana.satrdan("15.03.2026")) # UzbekSana ✅ Bitta so'z (cls) butun naqshni almashtiradi.
3. Nega bu mumkin
Pythonda sinf — obyekt (8.1-darsda ko'rgan edik):
type(Sana) # <class 'type'>
Sana.__name__ # 'Sana'
Sana(...) # chaqirish mumkin
f = Sana # o'zgaruvchiga solish
f(15, 3, 2026) # ✅ ishlaydi
def yarat(Sinf, *args): # funksiyaga uzatish
return Sinf(*args) Java da Class<T> bor, lekin u — metama'lumot obyekti, sinfning o'zi emas:
Class<Sana> c = Sana.class;
c.newInstance(); // ⚠️ refleksiya, checked exception4. cls qanday ishlaydi
classmethod — deskriptor:
class classmethod:
def __get__(self, obj, ega=None):
if ega is None:
ega = type(obj)
return MethodType(self.f, ega) # ⭐ SINFGA bog'lashUzbekSana.satrdan
# → Sana.__dict__["satrdan"].__get__(None, UzbekSana)
# → MethodType(f, UzbekSana)
# → chaqirilganda cls = UzbekSana ⭐ Sinf — argument sifatida uzatiladi, xuddi self kabi.
5. Amaliy foyda
a) Standart kutubxona bo'ylab:
dict.fromkeys("ab", 0) # ✅
class MeningDict(dict): pass
type(MeningDict.fromkeys("ab")) # MeningDict ✅
int.from_bytes(b"\x01", "big")
class MeningInt(int): pass
type(MeningInt.from_bytes(b"\x01", "big")) # MeningInt ✅
datetime.now(), datetime.fromisoformat(...)
Path.cwd(), Path.home()
Decimal.from_float(0.1) Bularning hammasi @classmethod — shuning uchun meros ishlaydi.
b) __init_subclass__ bilan birga:
class Plagin:
_royxat = {}
def __init_subclass__(cls, /, nom="", **kw):
super().__init_subclass__(**kw)
Plagin._royxat[nom or cls.__name__] = cls
@classmethod
def yarat(cls, nom, **kw):
return cls._royxat[nom](**kw) # ⭐ registryc) dataclass da:
@dataclass
class Sozlama:
port: int = 8000
@classmethod
def ishlab_chiqarish(cls, **kw):
return cls(port=443, **kw)
@dataclass
class KengaytirilganSozlama(Sozlama):
ssl: bool = True
KengaytirilganSozlama.ishlab_chiqarish() # ✅ to'g'ri tur6. Boshqa tillar
| Til | Mexanizm |
|---|---|
| Python | @classmethod + cls |
| Ruby | self sinf metodida = sinf |
| Smalltalk | Sinf — obyekt (Python shundan) |
| Java | static + Class<T> refleksiya |
| C# | static + generiklar |
| Kotlin | companion object (qisman) |
| Swift | class func + Self |
| Scala | object (companion) |
Ruby eng o'xshash:
class Sana
def self.satrdan(s)
new(...) # ⭐ self = chaqirilgan sinf
end
end
class UzbekSana < Sana; end
UzbekSana.satrdan("...").class # UzbekSana ✅Swift ham:
class Sana {
class func satrdan(_ s: String) -> Self {
return Self(...) // ⭐ Self — haqiqiy tur
}
}Swift Self kalit so'zi aynan Python cls bilan bir xil ma'noda.
Kotlin — qisman:
open class Sana {
companion object {
fun satrdan(s: String): Sana = Sana(...) // ⚠️ meros yo'q
}
} Kotlin companion object meros olinmaydi — Java bilan bir xil muammo.
7. staticmethod nima uchun kerak
Agar classmethod shu qadar yaxshi bo'lsa, staticmethod nega bor?
class Sana:
@staticmethod
def kabisami(yil: int) -> bool:
return yil % 4 == 0 and (yil % 100 != 0 or yil % 400 == 0) Bu funksiya sinfga bog'liq emas — cls ni olish noto'g'ri signal berardi:
@classmethod
def kabisami(cls, yil): # ⚠️ cls ishlatilmaydi
return ... O'quvchi "nega cls?" deb hayron bo'ladi.
Va staticmethod polimorfizmni ham beradi:
class Asos:
@staticmethod
def formatla(q): return str(q)
def chiqar(self):
return self.formatla(self.x) # ⭐ MRO bo'ylab qidiriladi
class Maxsus(Asos):
@staticmethod
def formatla(q): return f"[{q}]" # ✅ qayta aniqlandiModul funksiyasi bilan bu mumkin emas.
8. Tanlash qoidasi
class A:
# 1. self kerak → nusxa metod
def metod(self): return self.x
# 2. cls kerak (yaratish/sinf holati) → classmethod
@classmethod
def yarat(cls): return cls()
@classmethod
def statistika(cls): return cls._n
# 3. Ikkalasi ham kerak emas, lekin sinfga tegishli → staticmethod
@staticmethod
def tekshir(q): return q > 0
# 4. Sinfga umuman tegishli emas → MODUL funksiyasi9. Tarixiy izoh
classmethod va staticmethod Python 2.2 (2001) da qo'shildi — "yangi uslub sinflar" bilan birga. Undan oldin:
# Python 2.1 va oldin
class A:
def yarat(cls, x):
return cls(x)
yarat = classmethod(yarat) # ⚠️ dekorator sintaksisi yo'q edi Dekorator sintaksisi (@) faqat Python 2.4 (2004) da paydo bo'ldi (PEP 318) — va uning asosiy motivatsiyasi aynan classmethod/staticmethod edi:
"The current method of applying a transformation to a function or method places the actual transformation after the function body... For longer methods, the transformation is easily missed."
Ya'ni @ — classmethod ni ko'rinadigan qilish uchun o'ylab topilgan.
10. Xulosa
@classmethod bor, chunki:
- Sinf — obyekt, uni argument sifatida uzatish mumkin
- Fabrika metodlari meros bilan to'g'ri ishlaydi (
cls()) - Sinf holatini boshqarish kerak (registry, hisoblagich, kesh)
- Design Patterns naqshlarini (Factory Method) tilga kiritadi
Va staticmethod bor, chunki ba'zan metod sinfga tegishli, lekin uning holatiga bog'liq emas — cls olish noto'g'ri signal berardi.
Umumiy naqsh: Python boshqa tillarda dizayn naqshi bo'lgan narsani tilning bir qismi qiladi:
| Naqsh (GoF) | Pythonda |
|---|---|
| Factory Method | @classmethod |
| Strategy | Funksiya obyekti |
| Iterator | __iter__ |
| Decorator | @dekorator |
| Singleton | Modul |
| Observer | weakref + callback |
Shuning uchun Python kodida naqsh nomlari kamdan-kam uchraydi — ular tilga singib ketgan.
Nimani mustahkamlaydi: 2.1, 2.2, 2.5-bo'limlar.
Xulosa
Bu darsda @staticmethod va @classmethod ni o'rgandik.
Eng muhim uch fikr:
cls— chaqirilgan sinf, aniqlangan sinf emas.Bola.f()daclsBolabo'ladi, garchifOtada yozilgan bo'lsa ham. Aynan shuning uchun fabrika metodidacls(...)yozing, sinf nomini emas — shundaUzbekSana.satrdan()UzbekSanaqaytaradi va bitta metodni ham qayta yozish kerak bo'lmaydi.__init__— bitta yo'l, qolgani@classmethod.isinstanceshoxlanishi o'rnigaSana.satrdan(),Sana.izodan(),Sozlama.ishlab_chiqarish()— har birining nomi, hujjati va testi alohida. Standart kutubxona shunday qurilgan:dict.fromkeys,int.from_bytes,datetime.now,Path.home.cls._n += 1avlodga yangi atribut yaratadi. O'qish merosdan, yozish esacls.__dict__ga boradi — shuning uchun umumiy hisoblagich uchun aniq sinf nomi (Ota._n += 1) yozing. Har avlodga alohida hisoblagich kerak bo'lsa esacls._n += 1to'g'ri — muhimi, buni ongli tanlash.
Keyingi darsda dataclass ni to'liq ko'ramiz: avtomatik metodlar, field() parametrlari, __post_init__, frozen, slots va qachon oddiy sinf yozish kerakligi.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!