Mundarija (21)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. super() nima qaytaradi
- 2.2. Argumentsiz super()
- 2.3. super() — ota-sinf emas, MRO dagi keyingi
- 2.4. super().__init__() va hamkorlikdagi meros
- 2.5. Klassik xatolar
- 2.6. Qachon aniq shakl
- 2.7. super() va boshqa metodlar
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — super() aslida nima
- Misol 2 — super() — MRO da keyingi
- Misol 3 — Hamkorlikdagi __init__
- Misol 4 — Amaliy: qatlamli xizmat
- 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.7-dars: super()
8-QISM — OBYEKTGA YO'NALTIRILGAN DASTURLASH · 7-dars
1. Kirish va motivatsiya
Ko'pchilik super() ni shunday tushunadi:
class Bola(Ota):
def f(self):
return super().f() # "ota-sinfni chaqiradi"Bu — noto'g'ri. To'g'ri tushuncha:
super()ota-sinfni emas, MRO dagi keyingi sinfni qaytaradi.
Farq ko'p merosda ko'rinadi:
class A:
def f(self): return "A"
class B(A):
def f(self): return "B → " + super().f()
class C(A):
def f(self): return "C → " + super().f()
class D(B, C):
def f(self): return "D → " + super().f()
D().f() # 'D → B → C → A' ⭐ B.super() → C!
B().f() # 'B → A' ← bir xil kod, boshqa natija B ning super() chaqiruvi kontekstga qarab turli sinfga boradi. B.f kodi o'zgarmagan, lekin D orqali chaqirilganda C ga boradi.
Bu darsda:
-
super()aslida nima qaytaradi - Argumentsiz shakli qanday ishlaydi (
__class__yopilmasi) -
super()— MRO da keyingi, ota-sinf emas super().__init__()va hamkorlikdagi meros- Klassik xatolar:
Ota.metod(self),super(type(self), self) - Qachon
super()argumentlar bilan
2. Nazariya — chuqur tushuntirish
2.1. super() nima qaytaradi
class A:
def f(self): return "A.f"
class B(A):
def f(self):
s = super()
print(type(s)) # <class 'super'>
return s.f() super() — proxy obyekt. U atribut qidiruvini MRO ning ma'lum joyidan boshlaydi.
Ikki shakli:
super(Sinf, obj) # aniq shakl
super() # qisqa shakl (3.0+), faqat metod ichidasuper(B, b) ma'nosi:
bobyekti uchun atribut qidir, lekintype(b).__mro__daBdan keyin boshla.
class A:
def f(self): return "A.f"
class B(A):
def f(self): return "B.f"
class C(B):
def f(self): return "C.f"
c = C()
C.__mro__ # (C, B, A, object)
super(C, c).f() # 'B.f' ← C dan keyin
super(B, c).f() # 'A.f' ← B dan keyin
super(A, c).f() # AttributeError — object da f yo'q2.2. Argumentsiz super()
class B(A):
def f(self):
return super().f() # ≡ super(B, self).f()Qanday ishlaydi:
Kompilyator metod ichida super() yoki __class__ ni ko'rsa, funksiyaga yashirin yopilma o'zgaruvchisi __class__ qo'shadi:
class B(A):
def f(self):
print(__class__) # <class 'B'> ⭐ sehrli o'zgaruvchi
return super().f()
B.f.__code__.co_freevars # ('__class__',)super() ikki narsani oladi:
__class__— yopilmadanself— birinchi pozitsion argumentdan (co_varnames[0])
Shuning uchun super() ishlamaydigan joylar:
# 1. Sinf tashqarisida
def f(self):
return super().f() # ❌ RuntimeError
# 2. Statik metodda (self yo'q)
@staticmethod
def f():
return super().f() # ❌ RuntimeError
# 3. Ichki funksiyada
def f(self):
def ichki():
return super().f() # ❌ self ko'rinmaydi
return ichki()
# 4. Comprehension ichida (3.12 gacha)
def f(self):
return [super().f() for _ in range(1)] # ⚠️ Bunday joylarda aniq shakl: super(B, self).
2.3. super() — ota-sinf emas, MRO dagi keyingi
Bu — darsning eng muhim qismi.
class A:
def f(self): return "A"
class B(A):
def f(self): return "B → " + super().f()
class C(A):
def f(self): return "C → " + super().f()
class D(B, C):
def f(self): return "D → " + super().f()MRO:
D.__mro__ = (D, B, C, A, object)Chaqiruv zanjiri:
D().f()
→ D.f: "D → " + super().f()
super(D, d) → MRO da D dan keyin → B
→ B.f: "B → " + super().f()
super(B, d) → MRO da B dan keyin → C ⭐ A EMAS!
→ C.f: "C → " + super().f()
super(C, d) → MRO da C dan keyin → A
→ A.f: "A"
Natija: "D → B → C → A" B ning kodi super().f() — u A ni chaqiraman deb o'ylaydi, lekin D kontekstida C ga boradi.
Solishtiring:
B().f() # 'B → A' (MRO: B, A, object)
D().f() # 'D → B → C → A' Bir xil kod, turli natija — super() obyektning haqiqiy turiga bog'liq.
MRO hisoblash — 8.8-darsda.
2.4. super().__init__() va hamkorlikdagi meros
class Asos:
def __init__(self, **kw):
super().__init__(**kw) # ⭐ object.__init__()
class A(Asos):
def __init__(self, a, **kw):
super().__init__(**kw) # ⭐ qolganini uzatadi
self.a = a
class B(Asos):
def __init__(self, b, **kw):
super().__init__(**kw)
self.b = b
class C(A, B):
def __init__(self, c, **kw):
super().__init__(**kw)
self.c = c
C(a=1, b=2, c=3).__dict__ # {'b': 2, 'a': 1, 'c': 3} ✅ hammasiHamkorlikdagi meros qoidalari:
- Har
__init__super().__init__()chaqirsin — hatto ota-sinfobjectbo'lsa ham **kwargsbilan qolgan argumentlarni uzating- Nomli argumentlar ishlating — pozitsion tartib MRO da o'zgaradi
- Har sinf faqat o'z argumentlarini olsin
Buzilgan misol:
class A:
def __init__(self, a):
self.a = a # ⚠️ super() yo'q
class B:
def __init__(self, b):
self.b = b # ⚠️ super() yo'q
class C(A, B):
def __init__(self, a, b):
A.__init__(self, a) # ⚠️ aniq chaqiruv
B.__init__(self, b)Bu ishlaydi, lekin:
- MRO e'tiborga olinmaydi
- Olmos merosda
__init__ikki marta chaqirilishi mumkin - Yangi sinf qo'shilsa — buziladi
2.5. Klassik xatolar
A) Ota.metod(self) — MRO ni chetlab o'tadi:
class B(A):
def f(self):
return A.f(self) # ⚠️ super() emasMuammo: ko'p merosda A noto'g'ri sinf bo'lishi mumkin.
Olmos merosda ikki marta chaqirish:
class Asos:
def __init__(self):
print("Asos")
class A(Asos):
def __init__(self):
Asos.__init__(self) # ⚠️
print("A")
class B(Asos):
def __init__(self):
Asos.__init__(self) # ⚠️
print("B")
class C(A, B):
def __init__(self):
A.__init__(self)
B.__init__(self)
C() # Asos, A, Asos, B, C
# ⚠️ Asos IKKI MARTA super() bilan:
class A(Asos):
def __init__(self):
super().__init__()
print("A")
# ...
C() # Asos, B, A, C ✅ Asos BIR MARTAB) super(type(self), self) — cheksiz rekursiya:
class A:
def f(self): return "A"
class B(A):
def f(self):
return super(type(self), self).f() # ⚠️
class C(B):
pass
C().f() # ❌ RecursionErrorSabab: C() uchun type(self) — C, super(C, self) → B.f → yana type(self) = C → cheksiz.
super() yoki super(B, self).
C) super() ni pozitsion argumentlar bilan:
class A:
def __init__(self, x): self.x = x
class B:
def __init__(self, y): self.y = y
class C(A, B):
def __init__(self, x, y):
super().__init__(x) # ⚠️ A.__init__ ga boradi
# B.__init__ HECH QACHON chaqirilmaydi Nomli argumentlar va **kwargs.
2.6. Qachon aniq shakl
super(Sinf, obj) # nusxa uchun
super(Sinf, sinf2) # sinf uchun (classmethod da)Kerak bo'ladigan holatlar:
# 1. Sinf tashqarisida
def yamoq(self):
return super(B, self).f()
B.f = yamoq
# 2. Statik kontekstda
class B(A):
@staticmethod
def f():
return super(B, B).statik()
# 3. MRO ni ataylab sakrash
class C(B):
def f(self):
return super(B, self).f() # B ni O'TKAZIB YUBORISH
# 4. Metaklasslardaclassmethod da:
class B(A):
@classmethod
def yarat(cls):
return super().yarat() # ✅ ishlaydi — cls birinchi argument2.7. super() va boshqa metodlar
super() faqat __init__ uchun emas:
class Bola(Ota):
def __repr__(self):
return f"Bola({super().__repr__()})"
def __eq__(self, boshqa):
return super().__eq__(boshqa) and self.qoshimcha == boshqa.qoshimcha
@property
def qiymat(self):
return super().qiymat * 2 # ⚠️ property bilan ehtiyot
def __getattr__(self, nom):
return super().__getattr__(nom) @property bilan:
class A:
@property
def x(self): return 1
class B(A):
@property
def x(self):
return super().x * 2 # ✅ ishlaydiLekin setter'ni qayta aniqlash murakkabroq:
class B(A):
@A.x.setter # ⭐ ota-sinf property'sidan
def x(self, q):
self._x = q3. Tez ma'lumotnoma
Asosiy tushuncha
super() → ota-sinf EMAS
super() → MRO da JORIY sinfdan KEYINGI sinf
super() ≡ super(__class__, self) (metod ichida)
super(B, obj) obj uchun, MRO da B dan keyin
super(B, Sinf) sinf uchun (classmethod)Argumentsiz shakl
class B(A):
def f(self):
return super().f()
# Kompilyator qo'shadi:
# __class__ yopilma o'zgaruvchisi
# self — co_varnames[0] dan
⚠️ Ishlamaydi: sinf tashqarisida, @staticmethod da,
ichki funksiyada → aniq shakl ishlatingHamkorlikdagi meros
class A(Asos):
def __init__(self, a, **kw):
super().__init__(**kw) ⭐ HAR DOIM
self.a = a
Qoidalar:
1. Har __init__ super().__init__() chaqirsin
2. **kwargs bilan qolganini uzating
3. Nomli argumentlar (pozitsion emas)
4. Har sinf faqat o'z argumentini olsinXatolar
A.f(self) ⚠️ MRO ni chetlab o'tadi
super(type(self), self) ❌ RecursionError
super().__init__(x) ⚠️ ko'p merosda pozitsion4. Batafsil misollar
Misol 1 — super() aslida nima
"""super() ning ichki mexanizmi."""
print("=== 1. super() — proxy obyekt ===\n")
class A:
def f(self): return "A.f"
def g(self): return "A.g"
class B(A):
def f(self):
s = super()
print(f" type(super()) = {type(s)}")
print(f" repr = {s!r}")
return s.f()
print(f" B().f():")
print(f" natija: {B().f()!r}")
b = B()
s = super(B, b)
print(f"\n super(B, b):")
print(f" __self__ = {s.__self__}")
print(f" __self_class__ = {s.__self_class__.__name__}")
print(f" __thisclass__ = {s.__thisclass__.__name__}")
print(f"""
⭐ super obyekti UCH narsani saqlaydi:
__thisclass__ — qaysi sinfdan keyin boshlash ({s.__thisclass__.__name__})
__self__ — obyekt
__self_class__ — obyektning haqiqiy turi ({s.__self_class__.__name__})
""")
print("=== 2. MRO da joy ===\n")
class X:
def f(self): return "X.f"
class Y(X):
def f(self): return "Y.f"
class Z(Y):
def f(self): return "Z.f"
z = Z()
print(f" Z.__mro__ = {' → '.join(c.__name__ for c in Z.__mro__)}\n")
print(f" {'Ifoda':<22} {'Natija':<10} {'Izoh'}")
print(" " + "─" * 54)
IFODALAR = [
("z.f()", z.f(), "MRO boshidan"),
("super(Z, z).f()", super(Z, z).f(), "Z dan keyin → Y"),
("super(Y, z).f()", super(Y, z).f(), "Y dan keyin → X"),
]
for kod, natija, izoh in IFODALAR:
print(f" {kod:<22} {natija!r:<10} {izoh}")
try:
super(X, z).f()
except AttributeError as e:
print(f" {'super(X, z).f()':<22} {'❌':<10} X dan keyin → object (f yo'q)")
print("\n=== 3. ⭐ __class__ yopilmasi ===\n")
class Namoyish(A):
def super_bilan(self):
return super().f()
def class_bilan(self):
return __class__.__name__ # ⭐ sehrli o'zgaruvchi
def ikkalasi(self):
return f"{__class__.__name__}: {super().f()}"
def hech_biri(self):
return "oddiy metod"
print(f" Metodlarning yopilma o'zgaruvchilari (co_freevars):\n")
for nom in ["super_bilan", "class_bilan", "ikkalasi", "hech_biri"]:
f = Namoyish.__dict__[nom]
fv = f.__code__.co_freevars
print(f" {nom:<16} {fv}")
n = Namoyish()
print(f"\n Natijalar:")
print(f" n.super_bilan() = {n.super_bilan()!r}")
print(f" n.class_bilan() = {n.class_bilan()!r}")
print(f" n.ikkalasi() = {n.ikkalasi()!r}")
print(f"""
⭐ Kompilyator metod ichida super() yoki __class__ ni ko'rsa,
funksiyaga YASHIRIN __class__ yopilma o'zgaruvchisini qo'shadi.
super() ≡ super(__class__, self)
↑ ↑
yopilmadan co_varnames[0] dan
""")
print("=== ⚠️ 4. super() ishlamaydigan joylar ===\n")
print(" A) Sinf tashqarisida:")
def tashqi_metod(self):
try:
return super().f()
except RuntimeError as e:
return f"❌ RuntimeError: {e}"
class Sinov1(A):
pass
Sinov1.f2 = tashqi_metod
print(f" {Sinov1().f2()}")
def tashqi_togri(self):
return super(Sinov1, self).f() # ✅ aniq shakl
Sinov1.f3 = tashqi_togri
print(f" Aniq shakl: {Sinov1().f3()!r} ✅")
print("\n B) @staticmethod da:")
class Sinov2(A):
@staticmethod
def statik_yomon():
try:
return super().f()
except RuntimeError as e:
return f"❌ RuntimeError: {str(e)[:44]}"
@staticmethod
def statik_togri():
return super(Sinov2, Sinov2).f # ✅ aniq shakl
print(f" {Sinov2.statik_yomon()}")
print(f" Aniq shakl: {Sinov2.statik_togri()} ✅")
print("\n C) Ichki funksiyada:")
class Sinov3(A):
def metod(self):
def ichki():
try:
return super().f()
except (RuntimeError, TypeError) as e:
return f"❌ {type(e).__name__}"
return ichki()
def metod_togri(self):
ota_f = super().f # ✅ tashqarida oling
def ichki():
return ota_f()
return ichki()
print(f" {Sinov3().metod()}")
print(f" Aniq shakl: {Sinov3().metod_togri()!r} ✅")
print("\n D) @classmethod da — ✅ ISHLAYDI:")
class Sinov4(A):
@classmethod
def sinf_metod(cls):
return f"{cls.__name__}: {super().f}"
print(f" {Sinov4.sinf_metod()}")
print(f" ⭐ cls birinchi argument — super() uni topadi")
print("\n\n=== ⚠️ 5. super(type(self), self) — rekursiya ===\n")
class Baza:
def f(self): return "Baza.f"
class Orta(Baza):
def f(self):
return "Orta → " + super(type(self), self).f() # ⚠️
class Oxirgi(Orta):
pass
print(f" Orta().f() = {Orta().f()!r} ✅ ishlaydi")
try:
Oxirgi().f()
except RecursionError:
print(f" Oxirgi().f() → ❌ RecursionError")
print(f"""
⭐ SABAB:
Oxirgi() uchun type(self) = Oxirgi
super(Oxirgi, self) → MRO da Oxirgi dan keyin → Orta
Orta.f chaqiriladi → yana type(self) = Oxirgi → cheksiz
✅ TO'G'RI: super() yoki super(Orta, self)
""")
class OrtaTogri(Baza):
def f(self):
return "OrtaTogri → " + super().f()
class OxirgiTogri(OrtaTogri):
pass
print(f" OxirgiTogri().f() = {OxirgiTogri().f()!r} ✅")Natijaning muhim qismi:
=== 1. super() — proxy obyekt ===
B().f():
type(super()) = <class 'super'>
repr = <super: <class 'B'>, <B object>>
natija: 'A.f'
super(B, b):
__thisclass__ = B
__self_class__ = B
=== 2. MRO da joy ===
Ifoda Natija Izoh
──────────────────────────────────────────────────────
z.f() 'Z.f' MRO boshidan
super(Z, z).f() 'Y.f' Z dan keyin → Y
super(Y, z).f() 'X.f' Y dan keyin → X
=== 3. ⭐ __class__ yopilmasi ===
super_bilan ('__class__',)
class_bilan ('__class__',)
ikkalasi ('__class__',)
hech_biri ()
=== ⚠️ 5. super(type(self), self) — rekursiya ===
Orta().f() = 'Orta → Baza.f' ✅ ishlaydi
Oxirgi().f() → ❌ RecursionErrorNima ko'rsatdi: 2.1, 2.2, 2.5-bo'limlar.
Misol 2 — super() — MRO da keyingi
"""Ko'p merosda super() qanday harakat qiladi."""
print("=== ⭐ 1. Olmos merosi ===\n")
class A:
def f(self): return "A"
class B(A):
def f(self): return "B → " + super().f()
class C(A):
def f(self): return "C → " + super().f()
class D(B, C):
def f(self): return "D → " + super().f()
print(f" Ierarxiya:")
print(f" A")
print(f" / \\")
print(f" B C")
print(f" \\ /")
print(f" D\n")
for S in (A, B, C, D):
mro = " → ".join(c.__name__ for c in S.__mro__)
print(f" {S.__name__}.__mro__ = ({mro})")
print(f" {S.__name__}().f() = {S().f()!r}")
print()
print(f""" ⭐ ENG MUHIM KUZATUV:
B.f kodi: "B → " + super().f()
B() orqali: super(B, b) → MRO(B) = B,A,object → A
Natija: 'B → A'
D() orqali: super(B, d) → MRO(D) = D,B,C,A,object → C ⚠️
Natija: 'D → B → C → A'
BIR XIL KOD, TURLI NATIJA — chunki super() obyektning
HAQIQIY turiga (D) qaraydi, B ning ota-sinfiga emas.
""")
print("=== 2. Qadamma-qadam kuzatuv ===\n")
class A2:
def f(self):
print(f" A2.f: super() → object (f yo'q, to'xtaymiz)")
return "A2"
class B2(A2):
def f(self):
keyingi = super().__self_class__.__mro__
joy = keyingi.index(B2)
print(f" B2.f: MRO da B2 dan keyin → "
f"{keyingi[joy + 1].__name__}")
return "B2 → " + super().f()
class C2(A2):
def f(self):
keyingi = super().__self_class__.__mro__
joy = keyingi.index(C2)
print(f" C2.f: MRO da C2 dan keyin → "
f"{keyingi[joy + 1].__name__}")
return "C2 → " + super().f()
class D2(B2, C2):
def f(self):
keyingi = type(self).__mro__
print(f" D2.f: MRO da D2 dan keyin → {keyingi[1].__name__}")
return "D2 → " + super().f()
print(f" B2().f():")
n = B2().f()
print(f" → {n!r}\n")
print(f" D2().f():")
n = D2().f()
print(f" → {n!r}")
print("\n\n=== 3. ⚠️ Ota.metod(self) bilan solishtirish ===\n")
class Asos:
def __init__(self):
print(f" Asos.__init__")
self.tarix = ["Asos"]
class AliceYomon(Asos):
def __init__(self):
Asos.__init__(self) # ⚠️ aniq chaqiruv
print(f" Alice.__init__")
self.tarix.append("Alice")
class BobYomon(Asos):
def __init__(self):
Asos.__init__(self) # ⚠️
print(f" Bob.__init__")
self.tarix.append("Bob")
class IkkalasiYomon(AliceYomon, BobYomon):
def __init__(self):
AliceYomon.__init__(self)
BobYomon.__init__(self)
print(f" Ikkalasi.__init__")
self.tarix.append("Ikkalasi")
print(f" ⚠️ Ota.metod(self) bilan:")
o1 = IkkalasiYomon()
print(f" tarix = {o1.tarix}")
print(f" ⚠️ Asos IKKI MARTA chaqirildi, tarix qayta yozildi\n")
class AliceYaxshi(Asos):
def __init__(self):
super().__init__() # ✅
print(f" Alice.__init__")
self.tarix.append("Alice")
class BobYaxshi(Asos):
def __init__(self):
super().__init__() # ✅
print(f" Bob.__init__")
self.tarix.append("Bob")
class IkkalasiYaxshi(AliceYaxshi, BobYaxshi):
def __init__(self):
super().__init__() # ✅ bitta chaqiruv
print(f" Ikkalasi.__init__")
self.tarix.append("Ikkalasi")
print(f" ✅ super() bilan:")
o2 = IkkalasiYaxshi()
print(f" tarix = {o2.tarix}")
print(f" ✅ Asos BIR MARTA, hamma sinf o'z hissasini qo'shdi")
print(f"""
MRO: {' → '.join(c.__name__ for c in IkkalasiYaxshi.__mro__)}
⭐ super() zanjiri MRO ni TESKARI tartibda bajaradi:
Ikkalasi → Alice → Bob → Asos → (object)
Keyin qaytish: Asos → Bob → Alice → Ikkalasi
""")
print("\n=== 4. Mixin naqshi ===\n")
class Asos2:
def sorov(self, yol: str) -> str:
return f"javob({yol})"
class JurnalMixin:
"""⭐ super() bilan zanjirga ulanadi."""
def sorov(self, yol: str) -> str:
print(f" [jurnal] so'rov: {yol}")
natija = super().sorov(yol)
print(f" [jurnal] javob: {natija}")
return natija
class KeshMixin:
def __init__(self, *a, **kw):
super().__init__(*a, **kw)
self._kesh = {}
def sorov(self, yol: str) -> str:
if yol in self._kesh:
print(f" [kesh] URISH: {yol}")
return self._kesh[yol]
print(f" [kesh] o'tkazish: {yol}")
natija = super().sorov(yol)
self._kesh[yol] = natija
return natija
class QaytaUrinishMixin:
def sorov(self, yol: str) -> str:
for urinish in range(1, 4):
try:
return super().sorov(yol)
except Exception:
print(f" [urinish {urinish}] xato")
raise RuntimeError("3 urinish ham muvaffaqiyatsiz")
class Xizmat(JurnalMixin, KeshMixin, QaytaUrinishMixin, Asos2):
"""⭐ Mixinlar TARTIBI muhim."""
print(f" MRO: {' → '.join(c.__name__ for c in Xizmat.__mro__)}\n")
x = Xizmat()
print(f" Birinchi so'rov (/api):")
x.sorov("/api")
print(f"\n Ikkinchi so'rov (/api) — keshdan:")
x.sorov("/api")
print(f"""
⭐ MIXIN NAQSHI:
Har mixin super() ni chaqiradi → zanjir hosil bo'ladi.
Tartibni o'zgartirsangiz — xatti-harakat o'zgaradi:
(Jurnal, Kesh, ...) → jurnal keshdan OLDIN
(Kesh, Jurnal, ...) → jurnal faqat kesh o'tkazganda
""")
class Xizmat2(KeshMixin, JurnalMixin, QaytaUrinishMixin, Asos2):
pass
print(f" Tartib o'zgartirildi: KeshMixin, JurnalMixin, ...\n")
x2 = Xizmat2()
print(f" Birinchi so'rov:")
x2.sorov("/api")
print(f"\n Ikkinchi so'rov — keshdan (jurnal YO'Q):")
x2.sorov("/api")
print("\n\n=== 5. super() zanjiri to'xtashi ===\n")
class P1:
def f(self):
print(f" P1.f — super() CHAQIRMAYDI")
return "P1"
class P2:
def f(self):
print(f" P2.f")
return "P2 → " + super().f()
class P3:
def f(self):
print(f" P3.f")
return "P3"
class Yakun(P2, P1, P3):
def f(self):
print(f" Yakun.f")
return "Yakun → " + super().f()
print(f" MRO: {' → '.join(c.__name__ for c in Yakun.__mro__)}\n")
n = Yakun().f()
print(f"\n Natija: {n!r}")
print(f" ⚠️ P3.f CHAQIRILMADI — P1 zanjirni to'xtatdi")
print(f"""
⭐ QOIDA: hamkorlikdagi merosda HAR sinf super() ni
chaqirishi kerak — aks holda zanjir uziladi.
Faqat ENG OXIRGI sinf (odatda Asos) super() ni
chaqirmasligi mumkin — yoki object ga uzatadi.
""")Natijaning muhim qismi:
=== ⭐ 1. Olmos merosi ===
B.__mro__ = (B → A → object)
B().f() = 'B → A'
D.__mro__ = (D → B → C → A → object)
D().f() = 'D → B → C → A'
=== 3. ⚠️ Ota.metod(self) bilan solishtirish ===
⚠️ Ota.metod(self) bilan:
Asos.__init__
Alice.__init__
Asos.__init__
Bob.__init__
tarix = ['Asos', 'Bob', 'Ikkalasi']
⚠️ Asos IKKI MARTA chaqirildi, tarix qayta yozildi
✅ super() bilan:
Asos.__init__
Bob.__init__
Alice.__init__
tarix = ['Asos', 'Bob', 'Alice', 'Ikkalasi']
=== 4. Mixin naqshi ===
MRO: Xizmat → JurnalMixin → KeshMixin → QaytaUrinishMixin → Asos2
Ikkinchi so'rov (/api) — keshdan:
[jurnal] so'rov: /api
[kesh] URISH: /api
[jurnal] javob: javob(/api)Nima ko'rsatdi: 2.3, 2.5-bo'limlar.
Misol 3 — Hamkorlikdagi __init__
"""Ko'p merosda konstruktorlarni to'g'ri bog'lash."""
print("=== ⚠️ 1. Buzilgan yondashuv ===\n")
class AYomon:
def __init__(self, a):
self.a = a
print(f" A.__init__(a={a})")
class BYomon:
def __init__(self, b):
self.b = b
print(f" B.__init__(b={b})")
class CYomon(AYomon, BYomon):
def __init__(self, a, b):
super().__init__(a) # ⚠️ faqat A ga boradi
print(f" CYomon(1, 2):")
c = CYomon(1, 2)
print(f" __dict__ = {c.__dict__}")
print(f" ⚠️ B.__init__ CHAQIRILMADI — b atributi yo'q\n")
print(f" MRO: {' → '.join(k.__name__ for k in CYomon.__mro__)}")
print("\n\n=== ✅ 2. Hamkorlikdagi meros ===\n")
class Asos:
"""⭐ Zanjirning oxiri — object ga uzatadi."""
def __init__(self, **kw):
if kw:
print(f" Asos: qolgan argumentlar {kw}")
super().__init__() # object.__init__()
print(f" Asos.__init__")
class A(Asos):
def __init__(self, a, **kw):
super().__init__(**kw) # ⭐ qolganini uzatadi
self.a = a
print(f" A.__init__(a={a})")
class B(Asos):
def __init__(self, b, **kw):
super().__init__(**kw)
self.b = b
print(f" B.__init__(b={b})")
class C(Asos):
def __init__(self, c, **kw):
super().__init__(**kw)
self.c = c
print(f" C.__init__(c={c})")
class Hammasi(A, B, C):
def __init__(self, **kw):
super().__init__(**kw)
print(f" Hammasi.__init__")
print(f" MRO: {' → '.join(k.__name__ for k in Hammasi.__mro__)}\n")
print(f" Hammasi(a=1, b=2, c=3):")
h = Hammasi(a=1, b=2, c=3)
print(f"\n __dict__ = {h.__dict__} ✅ hammasi bor")
print(f"""
⭐ QOIDALAR:
1. Har __init__ super().__init__(**kw) chaqirsin
2. Har sinf o'z argumentini NOMLI oladi
3. Qolgani **kw orqali uzatiladi
4. Zanjir oxiridagi sinf super().__init__() (argumentsiz)
""")
print("\n=== 3. Turli kombinatsiyalar ===\n")
class FaqatAB(A, B):
def __init__(self, **kw):
super().__init__(**kw)
class FaqatBC(B, C):
def __init__(self, **kw):
super().__init__(**kw)
class Teskari(C, B, A):
def __init__(self, **kw):
super().__init__(**kw)
KOMBINATSIYALAR = [
(FaqatAB, {"a": 1, "b": 2}),
(FaqatBC, {"b": 2, "c": 3}),
(Teskari, {"a": 1, "b": 2, "c": 3}),
]
for Sinf, kw in KOMBINATSIYALAR:
print(f" {Sinf.__name__}({', '.join(f'{k}={v}' for k, v in kw.items())}):")
print(f" MRO: {' → '.join(k.__name__ for k in Sinf.__mro__[:-2])}")
obj = Sinf(**kw)
print(f" __dict__ = {obj.__dict__}\n")
print("=== ⚠️ 4. Xato: noto'g'ri argument ===\n")
print(f" Hammasi(a=1, b=2, c=3, xato=4):")
try:
Hammasi(a=1, b=2, c=3, xato=4)
except TypeError as e:
print(f" ⚠️ Chaqirilmadi (Asos qolgan argumentni yutdi)")
print(f"""
⚠️ Asos ichida kw ni tekshirmasak, xato JIMGINA o'tib ketadi.
✅ TO'G'RI Asos:
class Asos:
def __init__(self, **kw):
if kw:
raise TypeError(
f"Noma'lum argumentlar: {{sorted(kw)}}"
)
super().__init__()
""")
class AsosQatiy:
def __init__(self, **kw):
if kw:
raise TypeError(f"Noma'lum argumentlar: {sorted(kw)}")
super().__init__()
class A2(AsosQatiy):
def __init__(self, a, **kw):
super().__init__(**kw)
self.a = a
class B2(AsosQatiy):
def __init__(self, b, **kw):
super().__init__(**kw)
self.b = b
class C2(A2, B2):
def __init__(self, **kw):
super().__init__(**kw)
print(f" Qat'iy Asos bilan:")
print(f" C2(a=1, b=2) → {C2(a=1, b=2).__dict__} ✅")
try:
C2(a=1, b=2, xato=3)
except TypeError as e:
print(f" C2(a=1, b=2, xato=3) → ✅ TypeError: {e}")
print("\n\n=== 5. Ustuvorlikni to'g'ri o'rnatish ===\n")
class Sozlama:
"""Zanjir bo'ylab sozlamalarni yig'adi."""
def __init__(self, **kw):
self._d: dict = {}
super().__init__(**kw) if kw else None
self._birlashtir()
def _birlashtir(self):
"""MRO ni TESKARI aylanib sozlamalarni yig'adi."""
for Sinf in reversed(type(self).__mro__):
self._d.update(getattr(Sinf, "SOZLAMA", {}))
def __repr__(self):
return f"{type(self).__name__}({self._d})"
class Asosiy(Sozlama):
SOZLAMA = {"host": "localhost", "port": 8000, "debug": False}
class Xavfsizlik(Sozlama):
SOZLAMA = {"ssl": True, "port": 443}
class IshlabChiqarish(Sozlama):
SOZLAMA = {"debug": False, "jurnal": "xato"}
class Prod(IshlabChiqarish, Xavfsizlik, Asosiy):
SOZLAMA = {"host": "wisar.uz"}
class Dev(Asosiy):
SOZLAMA = {"debug": True, "jurnal": "hammasi"}
for Sinf in (Asosiy, Prod, Dev):
obj = Sinf()
mro = " → ".join(k.__name__ for k in Sinf.__mro__[:-2])
print(f" {Sinf.__name__:<10} MRO: {mro}")
print(f" {'':<10} {obj._d}\n")
print(f""" ⭐ reversed(MRO) bilan yig'ish:
Eng UZOQ ota-sinfdan boshlab, har biri ustidan yozadi.
Natija: eng YAQIN sinf ustuvor.
Prod: Asosiy → Xavfsizlik → IshlabChiqarish → Prod
port: 8000 → 443 → 443 → 443
host: localhost → ... → wisar.uz
""")
print("=== 6. __init_subclass__ va super() ===\n")
class Kuzatuv:
_sinflar: list[str] = []
def __init_subclass__(cls, /, teg: str = "", **kw):
super().__init_subclass__(**kw) # ⭐ SHART
cls.teg = teg or cls.__name__.lower()
Kuzatuv._sinflar.append(f"{cls.__name__}({cls.teg})")
class Aralash:
def __init_subclass__(cls, /, versiya: int = 1, **kw):
super().__init_subclass__(**kw) # ⭐ zanjir davom etadi
cls.versiya = versiya
class Birlashgan(Kuzatuv, Aralash, teg="asos", versiya=2):
pass
class Avlod(Birlashgan, teg="avlod", versiya=3):
pass
print(f" Ro'yxat: {Kuzatuv._sinflar}")
print(f"\n {'Sinf':<14} {'teg':<10} {'versiya'}")
print(" " + "─" * 34)
for S in (Birlashgan, Avlod):
print(f" {S.__name__:<14} {S.teg:<10} {S.versiya}")
print(f"""
⭐ __init_subclass__ da ham super() chaqirish SHART —
aks holda boshqa mixinlar ishlamaydi.
Argumentlar **kw orqali zanjir bo'ylab uzatiladi.
""")Natijaning muhim qismi:
=== ⚠️ 1. Buzilgan yondashuv ===
CYomon(1, 2):
A.__init__(a=1)
__dict__ = {'a': 1}
⚠️ B.__init__ CHAQIRILMADI — b atributi yo'q
=== ✅ 2. Hamkorlikdagi meros ===
MRO: Hammasi → A → B → C → Asos → object
Hammasi(a=1, b=2, c=3):
Asos.__init__
C.__init__(c=3)
B.__init__(b=2)
A.__init__(a=1)
Hammasi.__init__
__dict__ = {'c': 3, 'b': 2, 'a': 1} ✅ hammasi bor
=== 5. Ustuvorlikni to'g'ri o'rnatish ===
Prod MRO: Prod → IshlabChiqarish → Xavfsizlik → Asosiy
{'host': 'wisar.uz', 'port': 443, 'debug': False,
'ssl': True, 'jurnal': 'xato'}Nima ko'rsatdi: 2.4, 2.5-bo'limlar.
Misol 4 — Amaliy: qatlamli xizmat
"""super() bilan qurilgan mixin arxitekturasi."""
from __future__ import annotations
import time
import json
from typing import Any
print("=== QATLAMLI XIZMAT ===\n")
class Xizmat:
"""Asos — haqiqiy ish shu yerda."""
def __init__(self, nom: str = "xizmat", **kw):
if kw:
raise TypeError(f"Noma'lum argumentlar: {sorted(kw)}")
super().__init__()
self.nom = nom
self._chaqiruvlar = 0
def sorov(self, yol: str, **params: Any) -> dict:
"""Haqiqiy so'rov."""
self._chaqiruvlar += 1
time.sleep(0.001)
if yol == "/xato":
raise ConnectionError("Tarmoq mavjud emas")
return {"yol": yol, "params": params, "n": self._chaqiruvlar}
def __repr__(self):
return f"{type(self).__name__}({self.nom!r})"
class JurnalMixin:
"""Har so'rovni yozib boradi."""
def __init__(self, *, jurnal_darajasi: str = "info", **kw):
super().__init__(**kw) # ⭐
self.jurnal_darajasi = jurnal_darajasi
self.jurnal: list[str] = []
def sorov(self, yol: str, **params: Any) -> dict:
self.jurnal.append(f"→ {yol} {params}")
try:
natija = super().sorov(yol, **params) # ⭐
self.jurnal.append(f"← ok {natija['n']}")
return natija
except Exception as e:
self.jurnal.append(f"← XATO {type(e).__name__}")
raise
class KeshMixin:
"""Natijalarni keshlaydi."""
def __init__(self, *, kesh_hajmi: int = 100, **kw):
super().__init__(**kw)
self.kesh_hajmi = kesh_hajmi
self._kesh: dict[str, dict] = {}
self.urish = 0
self.otkazish = 0
def _kalit(self, yol: str, params: dict) -> str:
return f"{yol}?{json.dumps(params, sort_keys=True)}"
def sorov(self, yol: str, **params: Any) -> dict:
kalit = self._kalit(yol, params)
if kalit in self._kesh:
self.urish += 1
return self._kesh[kalit]
self.otkazish += 1
natija = super().sorov(yol, **params)
if len(self._kesh) >= self.kesh_hajmi:
self._kesh.pop(next(iter(self._kesh))) # eng eskisi
self._kesh[kalit] = natija
return natija
def kesh_holati(self) -> dict:
jami = self.urish + self.otkazish
return {"hajm": len(self._kesh), "urish": self.urish,
"otkazish": self.otkazish,
"nisbat": f"{self.urish / jami:.0%}" if jami else "—"}
class QaytaUrinishMixin:
"""Xato bo'lsa qayta urinadi."""
def __init__(self, *, urinishlar: int = 3, kutish: float = 0.001, **kw):
super().__init__(**kw)
self.urinishlar = urinishlar
self.kutish = kutish
self.qayta_urinishlar = 0
def sorov(self, yol: str, **params: Any) -> dict:
oxirgi: Exception | None = None
for n in range(1, self.urinishlar + 1):
try:
return super().sorov(yol, **params)
except (ConnectionError, TimeoutError) as e:
oxirgi = e
if n < self.urinishlar:
self.qayta_urinishlar += 1
time.sleep(self.kutish * n)
raise RuntimeError(
f"{self.urinishlar} urinish muvaffaqiyatsiz"
) from oxirgi
class OlchovMixin:
"""Vaqtni o'lchaydi."""
def __init__(self, **kw):
super().__init__(**kw)
self.olchovlar: list[float] = []
def sorov(self, yol: str, **params: Any) -> dict:
boshlanish = time.perf_counter()
try:
return super().sorov(yol, **params)
finally:
self.olchovlar.append(time.perf_counter() - boshlanish)
def olchov_holati(self) -> dict:
if not self.olchovlar:
return {"soni": 0}
return {
"soni": len(self.olchovlar),
"jami_ms": f"{sum(self.olchovlar) * 1000:.1f}",
"ortacha_ms": f"{sum(self.olchovlar) / len(self.olchovlar) * 1000:.2f}",
"maks_ms": f"{max(self.olchovlar) * 1000:.2f}",
}
class ChegaraMixin:
"""So'rovlar sonini cheklaydi."""
def __init__(self, *, chegara: int = 1000, **kw):
super().__init__(**kw)
self.chegara = chegara
self._soni = 0
def sorov(self, yol: str, **params: Any) -> dict:
if self._soni >= self.chegara:
raise RuntimeError(f"Chegara oshdi: {self.chegara}")
self._soni += 1
return super().sorov(yol, **params)
# ═══ KOMBINATSIYALAR ═══
class ToliqXizmat(OlchovMixin, JurnalMixin, KeshMixin,
QaytaUrinishMixin, ChegaraMixin, Xizmat):
"""Barcha qatlamlar."""
class OddiyXizmat(KeshMixin, Xizmat):
"""Faqat kesh."""
class IshonchliXizmat(QaytaUrinishMixin, JurnalMixin, Xizmat):
"""Qayta urinish + jurnal."""
print("1. MRO — qatlam tartibi:\n")
for Sinf in (ToliqXizmat, OddiyXizmat, IshonchliXizmat):
mro = " → ".join(c.__name__ for c in Sinf.__mro__[:-1])
print(f" {Sinf.__name__}:")
print(f" {mro}\n")
print("2. Hamkorlikdagi __init__:\n")
x = ToliqXizmat(
nom="asosiy",
jurnal_darajasi="debug",
kesh_hajmi=50,
urinishlar=2,
chegara=100,
)
print(f" {x!r}")
print(f" Barcha argumentlar zanjir bo'ylab taqsimlandi:\n")
for atr in ["nom", "jurnal_darajasi", "kesh_hajmi", "urinishlar", "chegara"]:
print(f" {atr:<20} {getattr(x, atr)!r}")
try:
ToliqXizmat(notogri=1)
except TypeError as e:
print(f"\n ToliqXizmat(notogri=1) → ✅ TypeError: {e}")
print("\n\n3. So'rovlar zanjiri:\n")
SOROVLAR = [
("/api/users", {"limit": 10}),
("/api/users", {"limit": 10}), # kesh
("/api/posts", {}),
("/api/users", {"limit": 20}), # boshqa params
("/api/posts", {}), # kesh
]
for yol, params in SOROVLAR:
natija = x.sorov(yol, **params)
print(f" {yol:<16} {str(params):<16} → n={natija['n']}")
print(f"\n Kesh: {x.kesh_holati()}")
print(f" Olchov: {x.olchov_holati()}")
print(f"\n Jurnal ({len(x.jurnal)} yozuv):")
for q in x.jurnal[:8]:
print(f" {q}")
print("\n\n4. Xato va qayta urinish:\n")
x2 = IshonchliXizmat(nom="ishonchli", urinishlar=3)
try:
x2.sorov("/xato")
except RuntimeError as e:
print(f" x2.sorov('/xato') → ✅ RuntimeError: {e}")
print(f" sabab: {type(e.__cause__).__name__}: {e.__cause__}")
print(f" qayta urinishlar: {x2.qayta_urinishlar}")
print(f"\n Jurnal:")
for q in x2.jurnal:
print(f" {q}")
print("\n\n5. ⭐ Tartib xatti-harakatni o'zgartiradi:\n")
class KeshOldin(KeshMixin, JurnalMixin, Xizmat):
"""Kesh birinchi — keshdan kelsa jurnal YO'Q."""
class JurnalOldin(JurnalMixin, KeshMixin, Xizmat):
"""Jurnal birinchi — hamma so'rov yoziladi."""
for Sinf in (KeshOldin, JurnalOldin):
s = Sinf(nom="t")
s.sorov("/a")
s.sorov("/a") # kesh
s.sorov("/a") # kesh
print(f" {Sinf.__name__:<14} 3 so'rov (2 tasi keshdan)")
print(f" {'':<14} jurnal yozuvlari: {len(s.jurnal)}")
print(f" {'':<14} kesh urish: {s.urish}, o'tkazish: {s.otkazish}\n")
print(f""" ⭐ KeshOldin: MRO da Kesh birinchi → keshdan qaytsa
Jurnal ga umuman bormaydi (1 yozuv)
JurnalOldin: MRO da Jurnal birinchi → har so'rov
yoziladi (3 × 2 = 6 yozuv)
""")
print("=== 6. Qatlamlarni tekshirish ===\n")
def qatlamlarni_korsat(Sinf: type) -> None:
"""Qaysi qatlam qaysi metodni ushlaydi."""
print(f" {Sinf.__name__}:")
for metod in ["__init__", "sorov"]:
egalar = [c.__name__ for c in Sinf.__mro__
if metod in c.__dict__ and c is not object]
print(f" {metod:<12} {' → '.join(egalar)}")
print()
for Sinf in (ToliqXizmat, OddiyXizmat, IshonchliXizmat):
qatlamlarni_korsat(Sinf)
print(f"""
⭐ BU ARXITEKTURA NEGA ISHLAYDI:
1. Har mixin super() ni chaqiradi → zanjir uzilmaydi
2. Har __init__ **kw bilan qolganini uzatadi
3. Har mixin O'Z argumentini NOMLI oladi
4. Asos sinf noma'lum argumentni ANIQLAYDI
5. Mixinlar bir-birini BILMAYDI — faqat super()
6. Tartibni o'zgartirish — xatti-harakatni o'zgartiradi
⚠️ CHEKLOVLARI:
• MRO ni tushunish kerak (8.8-dars)
• Nosozlikni topish qiyinroq
• Mixin tartibi hujjatlanishi shart
• Ko'p qatlam → sekinlashish
""")Natijaning muhim qismi:
1. MRO — qatlam tartibi:
ToliqXizmat:
ToliqXizmat → OlchovMixin → JurnalMixin → KeshMixin →
QaytaUrinishMixin → ChegaraMixin → Xizmat
2. Hamkorlikdagi __init__:
ToliqXizmat('asosiy')
Barcha argumentlar zanjir bo'ylab taqsimlandi:
nom 'asosiy'
jurnal_darajasi 'debug'
kesh_hajmi 50
urinishlar 2
ToliqXizmat(notogri=1) → ✅ TypeError: Noma'lum argumentlar: ['notogri']
3. So'rovlar zanjiri:
Kesh: {'hajm': 3, 'urish': 2, 'otkazish': 3, 'nisbat': '40%'}
Olchov: {'soni': 5, 'jami_ms': '5.1', 'ortacha_ms': '1.02', 'maks_ms': '1.76'}
5. ⭐ Tartib xatti-harakatni o'zgartiradi:
KeshOldin 3 so'rov (2 tasi keshdan)
jurnal yozuvlari: 2
JurnalOldin 3 so'rov (2 tasi keshdan)
jurnal yozuvlari: 6Nima ko'rsatdi: 2.3, 2.4, 2.7-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"super() ota-sinfni chaqiradi" |
MRO da keyingi sinfni |
"super() — funksiya chaqiruvi" |
Proxy obyekt qaytaradi |
"super() har joyda ishlaydi" |
Metod ichida, self bilan |
"Ota.metod(self) — super() bilan bir xil" |
MRO ni chetlab o'tadi |
"super(type(self), self) — to'g'ri shakl" |
RecursionError |
| "Bitta meros bo'lsa farq yo'q" | To'g'ri, lekin avlod qo'shilsa farq paydo bo'ladi |
"super() faqat __init__ uchun" |
Har metod uchun |
"@staticmethod da super() ishlaydi" |
self/cls yo'q |
6. Keng tarqalgan xatolar va yechimlari
1. super().__init__() unutish
class B(A):
def __init__(self, x, y):
self.y = y # ⚠️
super().__init__(x) # ✅2. Ota.__init__(self) ishlatish
Asos.__init__(self) # ⚠️ olmosda ikki marta
super().__init__() # ✅3. super(type(self), self)
super(type(self), self).f() # ❌ RecursionError
super().f() # ✅4. Ko'p merosda pozitsion argument
super().__init__(x, y) # ⚠️ faqat birinchi sinfga
super().__init__(x=x, **kw) # ✅5. Zanjirni uzish
class Mixin:
def f(self):
return "mixin" # ⚠️ super() yo'q
return "mixin " + super().f() # ✅6. @staticmethod da super()
@staticmethod
def f():
return super().g() # ❌ RuntimeError
return super(B, B).g() # ✅7. **kwargs uzatmaslik
def __init__(self, a):
super().__init__() # ⚠️ boshqa argumentlar yo'qoladi
def __init__(self, a, **kw):
super().__init__(**kw) # ✅8. __init_subclass__ da super() unutish
def __init_subclass__(cls, **kw):
cls.x = 1 # ⚠️ boshqa mixinlar ishlamaydi
super().__init_subclass__(**kw) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8.6-dars (o'tilgan): meros asoslari
- 8.8-dars: MRO va C3 linearizatsiyasi —
super()ning asosi - 8.9-dars: polimorfizm
- 8.18-dars: ABC —
super().__init_subclass__() - 9-qism: maxsus istisnolar —
super().__init__(xabar) - Django, DRF: mixin arxitekturasi to'liq
super()ga tayanadi - Maqola: "Python's super() considered super!" — Raymond Hettinger
8. Eng yaxshi amaliyotlar
Argumentsiz
super()ishlating.Ota.metod(self)— faqat maxsus holatlarda.Har
__init__super().__init__()chaqirsin. Hatto ota-sinfobjectbo'lsa ham.**kwargsbilan qolganini uzating. Hamkorlikdagi meros shunga tayanadi.Nomli argumentlar ishlating. Pozitsion tartib MRO da o'zgaradi.
Zanjir oxiridagi sinf noma'lum argumentni aniqlasin.
if kw: raise TypeError(...).Mixinlar
super()ni chaqirsin. Zanjir uzilmasin.Mixin tartibini hujjatlang. Tartib xatti-harakatni o'zgartiradi.
super(type(self), self)yozmang.RecursionErrorberadi.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
1. class A:
def f(self): return "A"
class B(A):
def f(self): return "B" + super().f()
print(B().f())
2. class A:
def f(self): return "A"
class B(A):
def f(self): return "B" + super().f()
class C(A):
def f(self): return "C" + super().f()
class D(B, C):
def f(self): return "D" + super().f()
print(D().f())
3. class A:
def __init__(self): self.x = 1
class B(A):
def __init__(self): super().__init__(); self.y = 2
print(sorted(B().__dict__))
4. class A: pass
class B(A):
def f(self): return type(super())
print(B().f())
5. class A:
def f(self): return "A"
class B(A):
def f(self): return "B"
b = B()
print(super(B, b).f())
6. class A:
def f(self): return "A"
class B(A):
def f(self): return __class__.__name__
print(B().f())
7. class A:
def f(self): return "A"
class B(A):
@staticmethod
def g():
try: return super().f()
except RuntimeError: return "xato"
print(B.g())
8. class A:
def __init__(self, **kw): super().__init__()
class B(A):
def __init__(self, b, **kw): super().__init__(**kw); self.b = b
class C(A):
def __init__(self, c, **kw): super().__init__(**kw); self.c = c
class D(B, C):
def __init__(self, **kw): super().__init__(**kw)
print(sorted(D(b=1, c=2).__dict__))
9. class A:
def f(self): return "A"
class B(A):
def f(self): return "B"
class C(B):
def f(self): return super(B, self).f()
print(C().f())
10. class A:
def f(self): return "A"
class B(A):
def f(self): return "B" + super().f()
class C(B): pass
print(C().f())
11. class A:
@classmethod
def f(cls): return cls.__name__
class B(A):
@classmethod
def f(cls): return "B" + super().f()
print(B.f())
12. print(super.__doc__.splitlines()[0])Javoblar
BADBCA—B.super()→C['x', 'y']<class 'super'>A—Bdan keyinB—__class__yopilmadanxato—@staticmethoddasuper()ishlamaydi['b', 'c']— hamkorlikdagi merosA—Bni o'tkazib yubordiBA—Cdafyo'qBB—cls=Bsuper() -> same as super(__class__, <first argument>)
Vazifa 2: Xatolarni tuzating
1. class B(A):
def __init__(self, x, y):
self.y = y
2. class C(A, B):
def __init__(self):
A.__init__(self)
B.__init__(self)
3. class B(A):
def f(self): return super(type(self), self).f()
4. class C(A, B):
def __init__(self, x, y): super().__init__(x, y)
5. class Mixin:
def f(self): return "mixin"
6. class B(A):
@staticmethod
def f(): return super().g()
7. class B(A):
def __init__(self, a): super().__init__()
8. class B(A):
def __init_subclass__(cls, **kw): cls.x = 1Javoblar
1. super().__init__(x) qo'shing
2. super().__init__() (va A, B da ham)
3. super().f()
4. super().__init__(x=x, y=y, **kw) va **kw qabul qiling
5. return "mixin " + super().f()
6. return super(B, B).g()
7. def __init__(self, a, **kw): super().__init__(**kw)
8. super().__init_subclass__(**kw) qo'shingVazifa 3: Mixin to'plami
Yozing:
Asossinf —bajar(malumot)metodiValidatsiyaMixin— kirishni tekshiradiKeshMixin— natijani keshlaydiJurnalMixin— yozib boradiOlchovMixin— vaqtni o'lchaydi- Barchasi hamkorlikdagi
__init__bilan - Turli kombinatsiyalar va tartiblarni sinang
Vazifa 4: super() kuzatuvchisi
Vosita yozing:
- Sinf ierarxiyasini olsin
- Har metod uchun
super()zanjirini ko'rsatsin - Zanjir uzilgan joylarni topsin (
super()chaqirmagan sinflar) Ota.metod(self)ishlatilgan joylarnisuper(type(self), self)xatosini- Vizual daraxt chiqarsin
Vazifa 5: Hamkorlikdagi __init__ tekshiruvchisi
- Sinf ierarxiyasidagi barcha
__init__ni tekshirsin super().__init__()chaqirmaganlarni topsin**kwargsqabul qilmaganlarni- Pozitsion argument uzatayotganlarni
- Zanjir oxirida tekshiruv yo'qligini
- Tuzatilgan versiyani taklif qilsin
Vazifa 6: Django uslubidagi ko'rinish
Korinishasos sinfi —bajar(sorov)AutentifikatsiyaMixin— foydalanuvchini tekshiradiRuxsatMixin— huquqlarniKeshMixin,JurnalMixin- Har biri
super()bilan zanjirga ulanadi - Xato bo'lsa zanjir to'xtasin (
403,401)
Vazifa 7: O'ylash
Nega Python 3 da super() argumentsiz ishlaydi, lekin Python 2 da super(B, self) yozish majburiy edi?
Javob
Chunki argumentsiz super() kompilyator sehri talab qiladi — va Python 2 da sinf jismini kompilyatsiya qilish boshqacha edi.
1. Python 2 dagi holat
# Python 2
class B(A):
def f(self):
return super(B, self).f() # ⚠️ ikkalasi ham majburiyMuammolar:
# a) Takrorlanish — sinf nomi ikki marta
class JudaUzunSinfNomi(A):
def f(self):
return super(JudaUzunSinfNomi, self).f() # ⚠️
# b) Sinf nomini o'zgartirsangiz — hamma joyda tuzatish
class YangiNom(A): # ⚠️ metodlar ichi eskicha qoldi
def f(self):
return super(EskiNom, self).f() # ❌ NameError
# c) Dekorator sinfni almashtirsa
@ozgartir
class B(A):
def f(self):
return super(B, self).f() # ⚠️ B endi boshqa sinf2. Nega bu qiyin edi
super() ishlashi uchun ikki narsa kerak:
- Joriy sinf — MRO da qayerdan boshlashni bilish uchun
- Obyekt —
self
self ni olish oson (birinchi pozitsion argument). Lekin joriy sinf — muammo:
class B(A):
def f(self):
# Bu funksiya kompilyatsiya paytida B ni BILMAYDI —
# B hali yaratilmagan!
... Sinf tanasi bajarilganda B nomi hali mavjud emas (8.2-darsda ko'rgan edik: type() chaqiruvi tananing oxirida bo'ladi).
Ishonchsiz yechimlar:
# a) type(self) — ❌ rekursiya
def f(self):
return super(type(self), self).f() # avlod bo'lsa cheksiz
# b) self.__class__ — ❌ bir xil muammo
# c) Global qidiruv — ❌ dekorator/qayta nomlashda buziladi
def f(self):
return super(globals()["B"], self).f()
# d) Frame tekshiruvi — ⚠️ sekin va mo'rt
import sys
def f(self):
ramka = sys._getframe(1)
...3. Python 3 yechimi — __class__ yopilmasi
PEP 3135 (2007, Calvin Spealman):
Kompilyator metod ichida super() yoki __class__ ni ko'rsa:
- Funksiyaga yashirin yopilma o'zgaruvchisi
__class__qo'shadi - Sinf yaratilgandan keyin uni to'ldiradi
class B(A):
def f(self):
return super().f()
B.f.__code__.co_freevars # ('__class__',)
B.f.__closure__[0].cell_contents # <class 'B'>Ya'ni __class__ — yopilma hujayrasi (cell), sinf yaratilganda to'ldiriladi.
Ko'rsatish:
class B(A):
def f(self):
print(__class__) # ⭐ hech qayerda e'lon qilinmagan
return super().f()__class__ — Pythonda yagona shunday sehrli o'zgaruvchi.
4. Nega bu Python 2 da qilinmadi
Texnik sabablar:
a) Yopilma mexanizmi cheklangan edi
Python 2 da nonlocal yo'q edi; yopilmalar faqat o'qish uchun ishlardi. __class__ hujayrasini keyinroq to'ldirish murakkabroq.
b) Eski va yangi uslub sinflari
Python 2 da ikki xil sinf bor edi:
class Eski: # eski uslub (classic)
pass
class Yangi(object): # yangi uslub
pass super() faqat yangi uslub sinflarda ishlardi. Kompilyator sehri ikkalasini ham qo'llab-quvvatlashi kerak bo'lardi.
class Eski:
def f(self):
return super(Eski, self).f() # ❌ TypeErrorPython 3 da eski uslub sinflar olib tashlandi — bu yo'lni ochdi.
c) Orqaga moslik
super — o'rnatilgan sinf, funksiya emas:
type(super) # <class 'type'>
super.__mro__ # (super, object)Uni argumentsiz chaqirish mumkin bo'lsa, mavjud kod xatti-harakati o'zgarardi.
5. Amalga oshirish tafsiloti
CPython da super.__init__ argumentsiz chaqirilganda:
/* Objects/typeobject.c, super_init_without_args */
/* 1. Joriy freymni ol */
frame = _PyThreadState_GetFrame(tstate);
/* 2. co_varnames[0] — birinchi argument (self/cls) */
obj = _PyFrame_GetLocalsArray(frame)[0];
/* 3. Yopilmadan __class__ ni topish */
for (i = 0; i < co->co_nlocalsplus; i++) {
if (_PyUnicode_EqualToASCIIId(name, &PyId___class__)) {
cell = _PyFrame_GetLocalsArray(frame)[i];
type = (PyTypeObject *) PyCell_GET(cell);
break;
}
} Ya'ni super() freymni tekshiradi — bu Pythonda kamdan-kam uchraydigan sehr.
Oqibatlari:
# 1. Freym bo'lmasa — ishlamaydi
lambda: super() # ❌
# 2. self birinchi argument bo'lmasa
def f(x, self): super() # ⚠️ x ni self deb oladi
# 3. __class__ yopilmada bo'lmasa
exec("super()") # ❌ RuntimeError6. Python 3.12 dagi yaxshilanish
3.12 gacha comprehension ichida super() muammoli edi:
class B(A):
def f(self):
return [super().g() for _ in range(3)] # ⚠️ 3.11 da xatoPEP 709 3.12-bob comprehension'larni inline qildi — endi ishlaydi.
7. Boshqa tillar
| Til | Sintaksis | Izoh |
|---|---|---|
| Python 3 | super().f() |
Kompilyator sehri |
| Python 2 | super(B, self).f() |
Qo'lda |
| Java | super.f() |
Kalit so'z, kompilyator biladi |
| C++ | Asos::f() |
Aniq sinf nomi |
| Ruby | super |
Argumentlarni avtomatik uzatadi |
| JavaScript | super.f() |
Kalit so'z |
| C# | base.f() |
Kalit so'z |
Ruby eng qisqa:
class B < A
def f(x, y)
super # x va y AVTOMATIK uzatiladi
super() # hech narsa uzatilmaydi
super(x) # faqat x
end
endPython super() ni kalit so'z qilmadi, chunki:
- Bu — obyekt, uni saqlash/uzatish mumkin
- Aniq shakl (
super(B, self)) hali ham kerak - Kalit so'z qo'shish — orqaga moslikni buzadi
8. Nega kalit so'z emas
# super() — obyekt, shuning uchun:
s = super() # ✅ saqlash mumkin
s.f()
s.g()
class B(A):
def f(self):
ota = super()
return ota.f() + ota.g() # ✅ ikki marta ishlatishJava da super — kalit so'z, uni saqlab bo'lmaydi.
Bundan tashqari, super — haqiqiy sinf:
super.__mro__ # (super, object)
isinstance(super(), super) # metod ichida TrueUni meros olish ham mumkin (juda kamdan-kam):
class MeningSuper(super):
pass9. Amaliy tavsiyalar
# ✅ Odatiy holat
class B(A):
def f(self):
return super().f()
# ✅ Aniq shakl kerak bo'lganda
def yamoq(self):
return super(B, self).f()
B.f = yamoq
# ✅ Statik kontekst
@staticmethod
def g():
return super(B, B).g()
# ✅ MRO ni sakrash
class C(B):
def f(self):
return super(B, self).f() # B ni o'tkazib yubor
# ❌ Hech qachon
super(type(self), self) # RecursionError10. Xulosa
Python 2 → 3 o'tishida super() soddalashtirilishi kichik ko'rinadi, lekin:
- Kod takrorlanishini yo'q qildi
- Qayta nomlash xatolarini oldini oldi
- Dekoratorlar bilan mos ishlaydi
- Mixin arxitekturasini soddalashtirdi
Buning narxi — kompilyator sehri (__class__ yopilmasi) va freym tekshiruvi. Bu Pythonning "aniqlik" tamoyiliga to'liq mos kelmaydi, lekin foydasi shu qadar katta ediki, PEP qabul qilindi.
Raymond Hettinger (CPython core dev) buni shunday izohlaydi:
"Argumentsiz
super()— Python 3 ning eng kam baholanadigan yaxshilanishlaridan biri. U ko'p merosni amalda ishlatiladigan qildi."
Nimani mustahkamlaydi: 2.1, 2.2, 2.5-bo'limlar.
Xulosa
Bu darsda super() ning haqiqiy ma'nosini o'rgandik.
Eng muhim uch fikr:
super()ota-sinfni emas, MRO dagi keyingi sinfni qaytaradi.super(B, obj)—type(obj).__mro__daBdan keyingi sinfdan qidirishni boshlaydigan proxy obyekt. Shuning uchunB.fichidagisuper().f()B()orqaliAga,D(B, C)()orqali esaCga boradi — bir xil kod, turli natija.Argumentsiz shakl kompilyator sehriga tayanadi. Metod ichida
super()yozilsa, kompilyator funksiyaga yashirin__class__yopilma o'zgaruvchisini qo'shadi vaselfni birinchi pozitsion argumentdan oladi. Shuning uchun u sinf tashqarisida,@staticmethodda va ichki funksiyada ishlamaydi — u yerlarda aniq shakl (super(B, self)) kerak.Hamkorlikdagi meros to'rt qoidaga tayanadi. Har
__init__super().__init__(**kw)chaqirsin; har sinf o'z argumentini nomli olsin; qolgani**kwargsorqali uzatilsin; zanjir oxiridagi sinf noma'lum argumentni aniqlasin.Ota.__init__(self)esa MRO ni chetlab o'tadi va olmos merosda ota-sinfni ikki marta chaqiradi.
Keyingi darsda MRO ning o'zini ko'ramiz: C3 linearizatsiyasi qanday hisoblanadi, nega ba'zi ierarxiyalar TypeError beradi va ko'p merosni qanday xavfsiz loyihalash mumkin.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!