Mundarija (21)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Uch oila
- 2.2. Operator hal qilish tartibi
- 2.3. += — __iadd__ vs __add__
- 2.4. Unar amallar
- 2.5. Turga o'girish
- 2.6. numbers ABC ierarxiyasi
- 2.7. Amaliy maslahatlar
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Uch oila
- Misol 2 — Turga o'girish
- Misol 3 — Matritsa va @
- Misol 4 — Amaliy: birlik 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.13-dars: Dunder: arifmetika
8-QISM — OBYEKTGA YO'NALTIRILGAN DASTURLASH · 13-dars
1. Kirish va motivatsiya
+ operatori — bitta belgi, lekin uch metod bilan bog'liq:
class Vektor:
def __init__(self, x, y): self.x, self.y = x, y
def __add__(self, b): ... # v + b
def __radd__(self, b): ... # b + v ⭐ teskari
def __iadd__(self, b): ... # v += b ⭐ joyidaVa bu uchtasi turli holatlarda chaqiriladi:
v = Vektor(1, 2)
v + Vektor(3, 4) # v.__add__ ✅
3 * v # v.__rmul__ ⭐ int bilmaydi
v += Vektor(1, 1) # v.__iadd__ ⭐ yoki __add__
sum([v1, v2, v3]) # 0 + v1 → v1.__radd__ ⚠️Bu esa chalkash:
lst = [1, 2]
lst2 = lst
lst += [3] # lst2 ham o'zgardi ⚠️
lst = lst + [4] # lst2 o'zgarmadi ✅
t = (1, 2)
t += (3,) # yangi tuple ✅ (tuple o'zgarmas)Bu darsda:
- Uch oila: oddiy, teskari (
__r*__), joyida (__i*__) NotImplementedva operator hal qilish tartibi-
+=—__iadd__vs__add__farqi - Unar amallar:
__neg__,__abs__,__invert__ - Turga o'girish:
__int__,__float__,__index__ numbersABC ierarxiyasi
2. Nazariya — chuqur tushuntirish
2.1. Uch oila
| Amal | Oddiy | Teskari | Joyida |
|---|---|---|---|
+ |
__add__ |
__radd__ |
__iadd__ |
- |
__sub__ |
__rsub__ |
__isub__ |
* |
__mul__ |
__rmul__ |
__imul__ |
/ |
__truediv__ |
__rtruediv__ |
__itruediv__ |
// |
__floordiv__ |
__rfloordiv__ |
__ifloordiv__ |
% |
__mod__ |
__rmod__ |
__imod__ |
** |
__pow__ |
__rpow__ |
__ipow__ |
@ |
__matmul__ |
__rmatmul__ |
__imatmul__ |
<< |
__lshift__ |
__rlshift__ |
__ilshift__ |
>> |
__rshift__ |
__rrshift__ |
__irshift__ |
& |
__and__ |
__rand__ |
__iand__ |
| |
__or__ |
__ror__ |
__ior__ |
^ |
__xor__ |
__rxor__ |
__ixor__ |
divmod() — __divmod__ / __rdivmod__.
2.2. Operator hal qilish tartibi
a + b uchun:
1. type(b) — type(a) ning AVLODI va __radd__ ni qayta aniqlagan?
→ b.__radd__(a) birinchi
2. a.__add__(b)
→ NotImplemented emas → natija
3. b.__radd__(a)
→ NotImplemented emas → natija
4. TypeError: unsupported operand type(s) for +: 'A' and 'B'class A:
def __add__(self, b):
print("A.__add__")
return NotImplemented
class B:
def __radd__(self, a):
print("B.__radd__")
return "natija"
A() + B()
# A.__add__
# B.__radd__
# 'natija' Nega __r*__ kerak:
3 * v # int.__mul__(3, v) → NotImplemented
# v.__rmul__(3) → ✅int sizning sinfingizni bilmaydi — shuning uchun NotImplemented qaytaradi.
2.3. += — __iadd__ vs __add__
a += bMexanizm:
1. a.__iadd__(b) bor bo'lsa
→ natija a ga qayta bog'lanadi
2. a.__add__(b) __iadd__ yo'q bo'lsa
→ natija a ga bog'lanadi
3. b.__radd__(a)
4. TypeError __iadd__ — obyektni joyida o'zgartirib, self qaytarish uchun.
class Royxat:
def __init__(self, el=None): self.el = list(el or [])
def __add__(self, b):
return Royxat(self.el + b.el) # ⭐ YANGI obyekt
def __iadd__(self, b):
self.el.extend(b.el) # ⭐ joyida
return self # ⚠️ QAYTARISH SHART Bu — list va tuple farqining sababi:
lst = [1, 2]
lst2 = lst
lst += [3] # list.__iadd__ — joyida
lst2 # [1, 2, 3] ⚠️ o'zgardi
t = (1, 2)
t2 = t
t += (3,) # tuple.__iadd__ yo'q → __add__
t2 # (1, 2) ✅ o'zgarmadiKlassik tuzoq (8.5-darsda ko'rgan edik):
class A:
lst = [] # sinf atributi
a = A()
a.lst += ["x"] # ⚠️ __iadd__ sinf ro'yxatini o'zgartiradi __iadd__ da return unutish:
def __iadd__(self, b):
self.el.extend(b.el) # ⚠️ return yo'q → None
a += b
a # None ⚠️2.4. Unar amallar
| Amal | Metod | Misol |
|---|---|---|
-a |
__neg__ |
-Vektor(1,2) |
+a |
__pos__ |
+Decimal("1.10") |
abs(a) |
__abs__ |
abs(Vektor(3,4)) |
~a |
__invert__ |
~Bayroq(5) |
round(a) |
__round__ |
round(Pul(1.5)) |
math.floor(a) |
__floor__ |
|
math.ceil(a) |
__ceil__ |
|
math.trunc(a) |
__trunc__ |
class Vektor:
def __neg__(self): return Vektor(-self.x, -self.y)
def __pos__(self): return self # odatda o'zi
def __abs__(self): return (self.x**2 + self.y**2) ** 0.5 __pos__ odatda self qaytaradi, lekin Decimal da u normallashtiradi:
from decimal import Decimal
+Decimal("1.10") # Decimal('1.10')
Decimal("1.10").normalize() # Decimal('1.1')2.5. Turga o'girish
| Funksiya | Metod | Talab |
|---|---|---|
int(a) |
__int__ |
int qaytarsin |
float(a) |
__float__ |
float |
complex(a) |
__complex__ |
complex |
bool(a) |
__bool__ |
bool (yoki __len__) |
bytes(a) |
__bytes__ |
bytes |
| indeks | __index__ |
int, yo'qotishsiz |
__index__ — __int__ dan farqi:
class A:
def __int__(self): return 5
lst = [1, 2, 3, 4, 5, 6]
lst[A()] # ❌ TypeError — __index__ kerak
int(A()) # 5 ✅ __index__ — yo'qotishsiz butun songa o'girish demakdir. float da __int__ bor, __index__ yo'q:
lst[2.0] # ❌ TypeError
hex(2.0) # ❌ TypeError
bin(True) # '0b1' ✅ bool.__index__ bor__index__ ishlatiladigan joylar: indekslash, kesish, hex(), oct(), bin(), range(), operator.index(), bitwise amallar.
Python 3.11+ da: __int__ faqat int() uchun; boshqa joylarda __index__ talab qilinadi.
__bool__ va __len__:
bool(x):
1. x.__bool__() bor bo'lsa
2. len(x) != 0 __len__ bor bo'lsa
3. True ikkalasi ham yo'q2.6. numbers ABC ierarxiyasi
from numbers import Number, Complex, Real, Rational, Integral
Number
└── Complex __complex__, __abs__, real, imag, conjugate
└── Real __float__, __trunc__, __floor__, __ceil__, __round__
└── Rational numerator, denominator
└── Integral __int__, __index__, bitwise amallarisinstance(5, Integral) # True
isinstance(5.0, Real) # True
isinstance(Fraction(1,2), Rational) # True
isinstance(complex(1,2), Complex) # True
isinstance(Decimal("1"), Real) # ⚠️ False! Decimal ataylab ro'yxatga olinmagan — u float bilan aralashishi mumkin emas.
2.7. Amaliy maslahatlar
Qaysi metodlarni yozish:
# Minimum — qiymat obyekti uchun
__add__, __radd__ # yig'indi ma'noli bo'lsa
__eq__, __hash__ # 8.12-dars
__repr__ # 8.11-dars
# Skalyar ko'paytirish
__mul__, __rmul__
# To'liq son kabi
__add__, __sub__, __mul__, __truediv__
+ hammasining __r*__ versiyasi
+ __neg__, __abs__ __r*__ ni unutmang:
class Pul:
def __mul__(self, n): return Pul(self.miqdor * n)
Pul(100) * 3 # ✅
3 * Pul(100) # ❌ TypeError __rmul__ = __mul__ (kommutativ bo'lsa).
Kommutativ bo'lmasa ehtiyot:
def __sub__(self, b): return Pul(self.m - b.m)
def __rsub__(self, b): return Pul(b - self.m) # ⭐ tartib teskari! sum() bilan ishlash:
sum([v1, v2, v3]) # 0 + v1 + v2 + v3
# ⚠️ 0.__add__(v1) → NotImplemented
# v1.__radd__(0) kerak
def __radd__(self, b):
if b == 0: return self # ⭐ sum() uchun
return self.__add__(b)
# yoki:
sum([v1, v2, v3], Vektor(0, 0)) # ✅ boshlang'ich qiymat3. Tez ma'lumotnoma
Uch oila
__add__(self, b) a + b
__radd__(self, b) b + a ⭐ b bilmasa
__iadd__(self, b) a += b ⭐ joyida, self qaytaring
Barcha amallar uchun: sub mul truediv floordiv mod pow
matmul lshift rshift and or xor Hal qilish tartibi (a + b)
1. b avlod va __radd__ qayta aniqlangan → b.__radd__(a)
2. a.__add__(b) → NotImplemented bo'lmasa
3. b.__radd__(a) → NotImplemented bo'lmasa
4. TypeError +=
1. a.__iadd__(b) → a ga qayta bog'lanadi
2. a.__add__(b) → __iadd__ yo'q bo'lsa
3. b.__radd__(a)
__iadd__ da return SHART!
list.__iadd__ → joyida (havolalar ta'sirlanadi)
tuple.__iadd__ yo'q → yangi obyektUnar
-a __neg__ abs(a) __abs__
+a __pos__ ~a __invert__
round(a) __round__ math.floor/ceil/truncTurga o'girish
int(a) __int__
float(a) __float__
bool(a) __bool__ → __len__ → True
bytes(a) __bytes__
lst[a] ⭐ __index__ (yo'qotishsiz!)4. Batafsil misollar
Misol 1 — Uch oila
"""Oddiy, teskari va joyida amallar."""
print("=== ⭐ 1. Hal qilish tartibi ===\n")
class Chap:
def __add__(self, b):
print(f" Chap.__add__({type(b).__name__})")
return NotImplemented
class Ong:
def __radd__(self, a):
print(f" Ong.__radd__({type(a).__name__})")
return "Ong hal qildi"
class Hech:
pass
print(f" Chap() + Ong():")
n = Chap() + Ong()
print(f" → {n!r}\n")
print(f" Chap() + Hech():")
try:
Chap() + Hech()
except TypeError as e:
print(f" ❌ TypeError: {e}\n")
print(f" 1 + Ong():")
n = 1 + Ong()
print(f" → {n!r}")
print(f" ⭐ int.__add__(1, Ong) → NotImplemented → Ong.__radd__")
print("\n=== ⚠️ 2. Avlod ustuvorligi ===\n")
class Ota:
def __add__(self, b):
print(f" Ota.__add__")
return "Ota"
class Bola(Ota):
def __radd__(self, a):
print(f" Bola.__radd__ (AVLOD — birinchi!)")
return "Bola"
print(f" Ota() + Bola():")
n = Ota() + Bola()
print(f" → {n!r}")
print(f"""
⭐ QOIDA: o'ng operand chap operandning AVLODI bo'lsa
va __radd__ ni QAYTA ANIQLAGAN bo'lsa —
u BIRINCHI chaqiriladi.
Sabab: avlod ota-sinfdan ko'proq biladi.
""")
print("=== ⚠️ 3. += mexanizmi ===\n")
class BilanIadd:
def __init__(self, el): self.el = list(el)
def __add__(self, b):
print(f" __add__ (yangi obyekt)")
return BilanIadd(self.el + b.el)
def __iadd__(self, b):
print(f" __iadd__ (joyida)")
self.el.extend(b.el)
return self # ⭐ SHART
def __repr__(self): return f"B({self.el})"
class Iaddsiz:
def __init__(self, el): self.el = list(el)
def __add__(self, b):
print(f" __add__ (yangi obyekt)")
return Iaddsiz(self.el + b.el)
def __repr__(self): return f"I({self.el})"
print(f" __iadd__ BOR:")
a = BilanIadd([1, 2])
a2 = a
a += BilanIadd([3])
print(f" a = {a}")
print(f" a2 = {a2} ⚠️ a2 ham o'zgardi (bir obyekt)")
print(f" a is a2 = {a is a2}\n")
print(f" __iadd__ YO'Q:")
b = Iaddsiz([1, 2])
b2 = b
b += Iaddsiz([3])
print(f" b = {b}")
print(f" b2 = {b2} ✅ o'zgarmadi")
print(f" b is b2 = {b is b2}")
print(f"""
⭐ MEXANIZM (a += b):
1. a.__iadd__(b) bor bo'lsa → natija a ga bog'lanadi
2. a.__add__(b) → natija a ga bog'lanadi
3. b.__radd__(a)
4. TypeError
""")
print("=== ⚠️ 4. list vs tuple ===\n")
lst = [1, 2]
lst2 = lst
lst += [3]
print(f" lst = [1,2]; lst2 = lst; lst += [3]")
print(f" lst = {lst}")
print(f" lst2 = {lst2} ⚠️ o'zgardi (list.__iadd__ joyida)")
lst3 = [1, 2]
lst4 = lst3
lst3 = lst3 + [3]
print(f"\n lst3 = lst3 + [3] (= bilan):")
print(f" lst3 = {lst3}")
print(f" lst4 = {lst4} ✅ o'zgarmadi")
t = (1, 2)
t2 = t
t += (3,)
print(f"\n t = (1,2); t2 = t; t += (3,)")
print(f" t = {t}")
print(f" t2 = {t2} ✅ o'zgarmadi (tuple.__iadd__ YO'Q)")
print(f"\n Metodlar mavjudligi:")
for tur in (list, tuple, set, dict, str, int):
iadd = "✅" if hasattr(tur, "__iadd__") else "❌"
ior = "✅" if hasattr(tur, "__ior__") else "❌"
print(f" {tur.__name__:<8} __iadd__: {iadd} __ior__: {ior}")
print("\n=== ⚠️ 5. __iadd__ da return unutish ===\n")
class Unutgan:
def __init__(self, el): self.el = list(el)
def __iadd__(self, b):
self.el.extend(b.el) # ⚠️ return yo'q
def __repr__(self): return f"U({self.el})"
u = Unutgan([1])
print(f" u = {u}")
u += Unutgan([2])
print(f" u += Unutgan([2]) dan keyin:")
print(f" u = {u} ⚠️ None!")
print(f"""
⚠️ __iadd__ None qaytarsa — a ga None bog'lanadi.
Bu — jimgina xato, topish qiyin.
✅ HAR DOIM return self
""")
print("=== 6. To'liq amallar to'plami ===\n")
class Son:
"""Barcha arifmetik amallarni qo'llab-quvvatlaydi."""
def __init__(self, q): self.q = float(q)
def _b(self, b):
"""Boshqa operandni songa o'giradi yoki None."""
if isinstance(b, Son): return b.q
if isinstance(b, (int, float)): return float(b)
return None
# ── Oddiy ──
def __add__(self, b):
x = self._b(b)
return Son(self.q + x) if x is not None else NotImplemented
def __sub__(self, b):
x = self._b(b)
return Son(self.q - x) if x is not None else NotImplemented
def __mul__(self, b):
x = self._b(b)
return Son(self.q * x) if x is not None else NotImplemented
def __truediv__(self, b):
x = self._b(b)
if x is None: return NotImplemented
if x == 0: raise ZeroDivisionError("Son nolga bo'lindi")
return Son(self.q / x)
def __floordiv__(self, b):
x = self._b(b)
return Son(self.q // x) if x is not None else NotImplemented
def __mod__(self, b):
x = self._b(b)
return Son(self.q % x) if x is not None else NotImplemented
def __pow__(self, b):
x = self._b(b)
return Son(self.q ** x) if x is not None else NotImplemented
def __divmod__(self, b):
x = self._b(b)
if x is None: return NotImplemented
d, m = divmod(self.q, x)
return (Son(d), Son(m))
# ── Teskari ──
def __radd__(self, b): return self.__add__(b) # kommutativ
def __rmul__(self, b): return self.__mul__(b) # kommutativ
def __rsub__(self, b):
x = self._b(b)
return Son(x - self.q) if x is not None else NotImplemented
def __rtruediv__(self, b):
x = self._b(b)
if x is None: return NotImplemented
if self.q == 0: raise ZeroDivisionError("Son nolga bo'lindi")
return Son(x / self.q)
def __rfloordiv__(self, b):
x = self._b(b)
return Son(x // self.q) if x is not None else NotImplemented
def __rmod__(self, b):
x = self._b(b)
return Son(x % self.q) if x is not None else NotImplemented
def __rpow__(self, b):
x = self._b(b)
return Son(x ** self.q) if x is not None else NotImplemented
# ── Unar ──
def __neg__(self): return Son(-self.q)
def __pos__(self): return Son(+self.q)
def __abs__(self): return Son(abs(self.q))
def __round__(self, n=0): return Son(round(self.q, n))
# ── Turga o'girish ──
def __int__(self): return int(self.q)
def __float__(self): return self.q
def __bool__(self): return self.q != 0
def __complex__(self): return complex(self.q)
def __repr__(self): return f"Son({self.q!r})"
def __eq__(self, b):
x = self._b(b)
return self.q == x if x is not None else NotImplemented
def __hash__(self): return hash(self.q)
s = Son(10)
AMALLAR = [
("s + 5", lambda: s + 5),
("5 + s", lambda: 5 + s),
("s + Son(5)", lambda: s + Son(5)),
("s - 3", lambda: s - 3),
("3 - s", lambda: 3 - s),
("s * 2", lambda: s * 2),
("2 * s", lambda: 2 * s),
("s / 4", lambda: s / 4),
("100 / s", lambda: 100 / s),
("s // 3", lambda: s // 3),
("s % 3", lambda: s % 3),
("s ** 2", lambda: s ** 2),
("2 ** s", lambda: 2 ** s),
("divmod(s, 3)", lambda: divmod(s, 3)),
("-s", lambda: -s),
("abs(Son(-5))", lambda: abs(Son(-5))),
("round(Son(3.7))", lambda: round(Son(3.7))),
("int(s)", lambda: int(s)),
("float(s)", lambda: float(s)),
("bool(Son(0))", lambda: bool(Son(0))),
("sum([Son(1), Son(2)])", lambda: sum([Son(1), Son(2)])),
("s == 10", lambda: s == 10),
("s / 0", lambda: s / 0),
("s + 'a'", lambda: s + "a"),
]
for kod, f in AMALLAR:
try:
natija = f"✅ {f()!r}"
except (TypeError, ZeroDivisionError) as e:
natija = f"❌ {type(e).__name__}: {str(e)[:34]}"
print(f" {kod:<24} {natija}")
print(f"""
⭐ sum() ISHLADI, chunki __radd__ int ni qabul qiladi:
sum([Son(1), Son(2)]) = 0 + Son(1) + Son(2)
↑ int.__add__ → NotImplemented
Son.__radd__(0) → Son(1)
""")Natijaning muhim qismi:
=== ⭐ 1. Hal qilish tartibi ===
Chap() + Ong():
Chap.__add__(Ong)
Ong.__radd__(Chap)
→ 'Ong hal qildi'
1 + Ong():
Ong.__radd__(int)
→ 'Ong hal qildi'
=== ⚠️ 3. += mexanizmi ===
__iadd__ BOR:
__iadd__ (joyida)
a = B([1, 2, 3])
a2 = B([1, 2, 3]) ⚠️ a2 ham o'zgardi
__iadd__ YO'Q:
__add__ (yangi obyekt)
b2 = I([1, 2]) ✅ o'zgarmadi
=== ⚠️ 5. __iadd__ da return unutish ===
u += Unutgan([2]) dan keyin:
u = None ⚠️
=== 6. To'liq amallar to'plami ===
5 + s ✅ Son(15.0)
3 - s ✅ Son(-7.0)
2 ** s ✅ Son(1024.0)
sum([Son(1), Son(2)]) ✅ Son(3.0)
s / 0 ❌ ZeroDivisionError: Son nolga bo'lindiNima ko'rsatdi: 2.1, 2.2, 2.3-bo'limlar.
Misol 2 — Turga o'girish
"""__int__, __index__, __bool__ va boshqalar."""
from decimal import Decimal
from fractions import Fraction
print("=== ⭐ 1. __int__ vs __index__ ===\n")
class FaqatInt:
def __init__(self, q): self.q = q
def __int__(self): return int(self.q)
def __repr__(self): return f"FaqatInt({self.q})"
class Indeksli:
def __init__(self, q): self.q = q
def __int__(self): return int(self.q)
def __index__(self): return int(self.q) # ⭐
def __repr__(self): return f"Indeksli({self.q})"
LST = ["a", "b", "c", "d", "e"]
SINOVLAR = [
("int(x)", lambda x: int(x)),
("LST[x]", lambda x: LST[x]),
("LST[x:x+2]", lambda x: LST[x:2]),
("hex(x)", lambda x: hex(x)),
("bin(x)", lambda x: bin(x)),
("oct(x)", lambda x: oct(x)),
("range(x)", lambda x: list(range(x))),
("'ab' * x", lambda x: "ab" * x),
("operator.index(x)", lambda x: __import__("operator").index(x)),
("[0]*x", lambda x: [0] * x),
]
print(f" {'Amal':<22} {'FaqatInt(2)':<24} {'Indeksli(2)'}")
print(" " + "─" * 62)
for kod, f in SINOVLAR:
natijalar = []
for x in (FaqatInt(2), Indeksli(2)):
try:
natijalar.append(f"✅ {f(x)!r}"[:22])
except TypeError:
natijalar.append("❌ TypeError")
print(f" {kod:<22} {natijalar[0]:<24} {natijalar[1]}")
print(f"""
⭐ __index__ MA'NOSI:
"Bu obyektni butun songa YO'QOTISHSIZ o'girish mumkin"
__int__ → o'girish mumkin (yo'qotish bo'lishi mumkin)
__index__ → aniq butun son (indeks sifatida ishlatsa bo'ladi)
⚠️ float da __int__ bor, __index__ YO'Q:
""")
for x in [2.0, 2.5, True, Fraction(4, 2), Decimal("2")]:
ind = "✅" if hasattr(type(x), "__index__") else "❌"
try:
LST[x]
natija = "✅"
except TypeError:
natija = "❌"
print(f" {x!r:<16} __index__: {ind} LST[x]: {natija}")
print(f"""
⭐ Sabab: LST[2.0] va LST[2.5] chalkash bo'lardi —
birinchisi ishlab, ikkinchisi ishlamasdi.
Python ikkalasini ham rad etadi.
""")
print("=== 2. __bool__ va __len__ ===\n")
class BilanBool:
def __init__(self, q): self.q = q
def __bool__(self): return self.q > 0
def __repr__(self): return f"Bool({self.q})"
class BilanLen:
def __init__(self, n): self.n = n
def __len__(self): return self.n
def __repr__(self): return f"Len({self.n})"
class Ikkalasi:
def __bool__(self):
print(f" __bool__ chaqirildi")
return False
def __len__(self):
print(f" __len__ chaqirildi")
return 10
class HechBiri:
def __repr__(self): return "Hech()"
print(f" {'Obyekt':<16} {'bool()':<10} {'Manba'}")
print(" " + "─" * 46)
for x, manba in [
(BilanBool(5), "__bool__"),
(BilanBool(-1), "__bool__"),
(BilanLen(3), "__len__ != 0"),
(BilanLen(0), "__len__ == 0"),
(HechBiri(), "sukut True"),
]:
print(f" {x!r:<16} {bool(x)!s:<10} {manba}")
print(f"\n Ikkalasi ham bor:")
print(f" bool(Ikkalasi()) →")
n = bool(Ikkalasi())
print(f" natija: {n} ⭐ __bool__ ustuvor")
print(f"""
⭐ TARTIB:
1. __bool__() bor bo'lsa
2. len(x) != 0 __len__ bor bo'lsa
3. True ikkalasi ham yo'q
⚠️ __bool__ FAQAT bool qaytarishi kerak:
""")
class YomonBool:
def __bool__(self): return 1 # ⚠️ int
try:
bool(YomonBool())
except TypeError as e:
print(f" return 1 → ❌ TypeError: {e}")
print("\n=== 3. Barcha o'girishlar ===\n")
class Toliq:
"""Barcha turga o'girish metodlari."""
def __init__(self, q): self.q = q
def __int__(self): return int(self.q)
def __float__(self): return float(self.q)
def __complex__(self): return complex(self.q, 0)
def __bool__(self): return bool(self.q)
def __index__(self): return int(self.q)
def __bytes__(self): return str(self.q).encode()
def __str__(self): return f"Toliq: {self.q}"
def __repr__(self): return f"Toliq({self.q!r})"
def __format__(self, s): return format(self.q, s)
def __hash__(self): return hash(self.q)
def __round__(self, n=None):
return Toliq(round(self.q, n) if n is not None else round(self.q))
def __floor__(self):
import math
return Toliq(math.floor(self.q))
def __ceil__(self):
import math
return Toliq(math.ceil(self.q))
def __trunc__(self):
import math
return Toliq(math.trunc(self.q))
import math
t = Toliq(3.7)
OGIRISHLAR = [
("int(t)", lambda: int(t)),
("float(t)", lambda: float(t)),
("complex(t)", lambda: complex(t)),
("bool(t)", lambda: bool(t)),
("bytes(t)", lambda: bytes(t)),
("str(t)", lambda: str(t)),
("repr(t)", lambda: repr(t)),
("format(t, '.1f')", lambda: format(t, ".1f")),
("hash(t) % 1000", lambda: hash(t) % 1000),
("round(t)", lambda: round(t)),
("round(t, 1)", lambda: round(t, 1)),
("math.floor(t)", lambda: math.floor(t)),
("math.ceil(t)", lambda: math.ceil(t)),
("math.trunc(t)", lambda: math.trunc(t)),
("[0,1,2,3][Toliq(2)]", lambda: [0, 1, 2, 3][Toliq(2)]),
("hex(Toliq(255))", lambda: hex(Toliq(255))),
]
for kod, f in OGIRISHLAR:
try:
print(f" {kod:<24} → {f()!r}")
except Exception as e:
print(f" {kod:<24} → ❌ {type(e).__name__}")
print("\n=== 4. numbers ABC ierarxiyasi ===\n")
from numbers import Number, Complex, Real, Rational, Integral
QIYMATLAR = [
5, 5.0, True, Fraction(1, 2), complex(1, 2),
Decimal("1.5"), "matn", [1],
]
print(f" {'Qiymat':<18} {'Number':<9} {'Complex':<9} {'Real':<8} "
f"{'Rational':<10} {'Integral'}")
print(" " + "─" * 68)
for q in QIYMATLAR:
qatorlar = [
"✅" if isinstance(q, A) else " "
for A in (Number, Complex, Real, Rational, Integral)
]
print(f" {q!r:<18} {qatorlar[0]:<9} {qatorlar[1]:<9} "
f"{qatorlar[2]:<8} {qatorlar[3]:<10} {qatorlar[4]}")
print(f"""
⭐ IERARXIYA:
Number
└── Complex __complex__, __abs__, real, imag, conjugate
└── Real __float__, __trunc__, __floor__, __ceil__, __round__
└── Rational numerator, denominator
└── Integral __int__, __index__, bitwise
⚠️ Decimal Real EMAS — ataylab:
Decimal float bilan aralashishi xato natija berardi:
Decimal('0.1') + 0.1 → TypeError ✅ himoya
""")
try:
Decimal("0.1") + 0.1
except TypeError as e:
print(f" Decimal('0.1') + 0.1 → ❌ TypeError: {str(e)[:52]}")
print(f" Decimal('0.1') + Fraction(1,10) → "
f"{Decimal('0.1') + Decimal(1) / Decimal(10)} ✅ aniq o'girib")
print(f" ⚠️ Decimal(str(Fraction(1, 10))) ishlamaydi: str → '1/10',")
print(f" Decimal esa bu ko'rinishni tushunmaydi (InvalidOperation).")
print(f" To'g'risi: Decimal(f.numerator) / Decimal(f.denominator)")
print("\n=== 5. O'z sinfini ro'yxatga olish ===\n")
class MeningSonim:
def __init__(self, q): self.q = q
def __int__(self): return int(self.q)
def __float__(self): return float(self.q)
def __index__(self): return int(self.q)
def __abs__(self): return MeningSonim(abs(self.q))
def __neg__(self): return MeningSonim(-self.q)
def __pos__(self): return self
def __add__(self, b): return MeningSonim(self.q + float(b))
def __radd__(self, b): return self.__add__(b)
def __mul__(self, b): return MeningSonim(self.q * float(b))
def __rmul__(self, b): return self.__mul__(b)
def __truediv__(self, b): return MeningSonim(self.q / float(b))
def __rtruediv__(self, b): return MeningSonim(float(b) / self.q)
def __sub__(self, b): return MeningSonim(self.q - float(b))
def __rsub__(self, b): return MeningSonim(float(b) - self.q)
def __pow__(self, b): return MeningSonim(self.q ** float(b))
def __rpow__(self, b): return MeningSonim(float(b) ** self.q)
def __eq__(self, b):
try: return self.q == float(b)
except (TypeError, ValueError): return NotImplemented
def __lt__(self, b):
try: return self.q < float(b)
except (TypeError, ValueError): return NotImplemented
def __le__(self, b):
try: return self.q <= float(b)
except (TypeError, ValueError): return NotImplemented
def __hash__(self): return hash(self.q)
def __floor__(self): return math.floor(self.q)
def __ceil__(self): return math.ceil(self.q)
def __trunc__(self): return math.trunc(self.q)
def __round__(self, n=None): return round(self.q, n)
def __repr__(self): return f"MeningSonim({self.q!r})"
@property
def real(self): return self.q
@property
def imag(self): return 0.0
def conjugate(self): return self
def __complex__(self): return complex(self.q, 0)
print(f" Ro'yxatga olishdan oldin:")
m = MeningSonim(5)
for A in (Number, Complex, Real, Integral):
print(f" isinstance(m, {A.__name__}) = {isinstance(m, A)}")
Real.register(MeningSonim) # ⭐
print(f"\n Real.register(MeningSonim) dan keyin:")
for A in (Number, Complex, Real, Integral):
print(f" isinstance(m, {A.__name__}) = {isinstance(m, A)}")
print(f"\n Amallar:")
for kod, f in [
("m + 3", lambda: m + 3),
("3 + m", lambda: 3 + m),
("m * 2", lambda: m * 2),
("10 / m", lambda: 10 / m),
("m ** 2", lambda: m ** 2),
("abs(-m)", lambda: abs(-m)),
("m < 10", lambda: m < 10),
("sorted([MeningSonim(3), m])",
lambda: sorted([MeningSonim(3), m])),
("math.floor(MeningSonim(3.7))",
lambda: math.floor(MeningSonim(3.7))),
("[0,1,2,3,4,5][m]", lambda: [0, 1, 2, 3, 4, 5][m]),
]:
print(f" {kod:<32} → {f()!r}")
print(f"""
⚠️ register() TEKSHIRMAYDI — barcha kerakli metodlarni
o'zingiz yozishingiz kerak.
✅ Muqobil: numbers.Real dan MEROS oling —
abstrakt metodlar majburiy bo'ladi.
""")Natijaning muhim qismi:
=== ⭐ 1. __int__ vs __index__ ===
Amal FaqatInt(2) Indeksli(2)
──────────────────────────────────────────────────────────────
int(x) ✅ 2 ✅ 2
LST[x] ❌ TypeError ✅ 'c'
hex(x) ❌ TypeError ✅ '0x2'
range(x) ❌ TypeError ✅ [0, 1]
2.0 __index__: ❌ LST[x]: ❌
True __index__: ✅ LST[x]: ✅
=== 4. numbers ABC ierarxiyasi ===
Qiymat Number Complex Real Rational Integral
────────────────────────────────────────────────────────────────────
5 ✅ ✅ ✅ ✅ ✅
5.0 ✅ ✅ ✅
True ✅ ✅ ✅ ✅ ✅
Fraction(1, 2) ✅ ✅ ✅ ✅
Decimal('1.5') ✅
Decimal('0.1') + 0.1 → ❌ TypeError: unsupported operand type(s)Nima ko'rsatdi: 2.5, 2.6-bo'limlar.
Misol 3 — Matritsa va @
"""Matritsa amallar — @ operatori bilan."""
from __future__ import annotations
print("=== MATRITSA ===\n")
class Matritsa:
"""To'liq arifmetika bilan matritsa."""
__slots__ = ("_q", "qatorlar", "ustunlar")
def __init__(self, qiymatlar):
q = [list(map(float, r)) for r in qiymatlar]
if not q or not q[0]:
raise ValueError("Bo'sh matritsa")
if len({len(r) for r in q}) != 1:
raise ValueError("Qatorlar uzunligi bir xil bo'lsin")
object.__setattr__(self, "_q", q)
object.__setattr__(self, "qatorlar", len(q))
object.__setattr__(self, "ustunlar", len(q[0]))
# ── Fabrika ──
@classmethod
def nol(cls, n, m=None):
m = m or n
return cls([[0] * m for _ in range(n)])
@classmethod
def birlik(cls, n):
return cls([[1 if i == j else 0 for j in range(n)]
for i in range(n)])
# ── Ko'rinish ──
def __repr__(self):
return f"Matritsa({self._q!r})"
def __str__(self):
kenglik = max(len(f"{x:g}") for r in self._q for x in r)
return "\n".join(
"│ " + " ".join(f"{x:>{kenglik}g}" for x in r) + " │"
for r in self._q
)
def __format__(self, spec):
if spec == "olcham":
return f"{self.qatorlar}×{self.ustunlar}"
if not spec:
return str(self)
return format(str(self), spec)
# ── Konteyner ──
def __getitem__(self, indeks):
if isinstance(indeks, tuple):
i, j = indeks
return self._q[i][j]
return list(self._q[indeks])
def __len__(self):
return self.qatorlar
def __iter__(self):
return iter(list(r) for r in self._q)
# ── Taqqoslash ──
def __eq__(self, b):
if not isinstance(b, Matritsa):
return NotImplemented
return self._q == b._q
def __hash__(self):
return hash(tuple(tuple(r) for r in self._q))
# ── Arifmetika ──
def __add__(self, b):
if isinstance(b, (int, float)):
return Matritsa([[x + b for x in r] for r in self._q])
if not isinstance(b, Matritsa):
return NotImplemented
if (self.qatorlar, self.ustunlar) != (b.qatorlar, b.ustunlar):
raise ValueError(
f"O'lchamlar mos emas: {self:olcham} + {b:olcham}"
)
return Matritsa([[x + y for x, y in zip(r1, r2)]
for r1, r2 in zip(self._q, b._q)])
def __radd__(self, b):
return self.__add__(b)
def __sub__(self, b):
if isinstance(b, (int, float)):
return Matritsa([[x - b for x in r] for r in self._q])
if not isinstance(b, Matritsa):
return NotImplemented
return self.__add__(-b)
def __rsub__(self, b):
return (-self).__add__(b)
def __mul__(self, b):
"""⭐ Elementma-element yoki skalyar."""
if isinstance(b, (int, float)):
return Matritsa([[x * b for x in r] for r in self._q])
if not isinstance(b, Matritsa):
return NotImplemented
if (self.qatorlar, self.ustunlar) != (b.qatorlar, b.ustunlar):
raise ValueError("Elementma-element uchun o'lcham bir xil bo'lsin")
return Matritsa([[x * y for x, y in zip(r1, r2)]
for r1, r2 in zip(self._q, b._q)])
def __rmul__(self, b):
return self.__mul__(b)
def __matmul__(self, b):
"""⭐ @ — haqiqiy matritsa ko'paytmasi (PEP 465)."""
if not isinstance(b, Matritsa):
return NotImplemented
if self.ustunlar != b.qatorlar:
raise ValueError(
f"Ko'paytirib bo'lmaydi: {self:olcham} @ {b:olcham} "
f"({self.ustunlar} != {b.qatorlar})"
)
return Matritsa([
[sum(self._q[i][k] * b._q[k][j] for k in range(self.ustunlar))
for j in range(b.ustunlar)]
for i in range(self.qatorlar)
])
def __truediv__(self, b):
if isinstance(b, (int, float)):
if b == 0:
raise ZeroDivisionError("Matritsa nolga bo'lindi")
return Matritsa([[x / b for x in r] for r in self._q])
return NotImplemented
def __pow__(self, n):
"""⭐ Matritsa darajasi (@ bilan)."""
if not isinstance(n, int) or n < 0:
return NotImplemented
if self.qatorlar != self.ustunlar:
raise ValueError("Faqat kvadrat matritsa")
natija = Matritsa.birlik(self.qatorlar)
asos = self
while n: # tez darajaga ko'tarish
if n & 1:
natija = natija @ asos
asos = asos @ asos
n >>= 1
return natija
# ── Unar ──
def __neg__(self):
return Matritsa([[-x for x in r] for r in self._q])
def __pos__(self):
return self
def __abs__(self):
return Matritsa([[abs(x) for x in r] for r in self._q])
def __round__(self, n=0):
return Matritsa([[round(x, n) for x in r] for r in self._q])
def __bool__(self):
return any(x != 0 for r in self._q for x in r)
# ── Xususiyatlar ──
@property
def T(self):
"""Transponirlangan."""
return Matritsa([[self._q[i][j] for i in range(self.qatorlar)]
for j in range(self.ustunlar)])
@property
def iz(self):
"""Diagonal yig'indisi."""
if self.qatorlar != self.ustunlar:
raise ValueError("Faqat kvadrat matritsa")
return sum(self._q[i][i] for i in range(self.qatorlar))
def determinant(self):
if self.qatorlar != self.ustunlar:
raise ValueError("Faqat kvadrat matritsa")
n = self.qatorlar
if n == 1:
return self._q[0][0]
if n == 2:
return (self._q[0][0] * self._q[1][1]
- self._q[0][1] * self._q[1][0])
d = 0.0
for j in range(n):
minor = Matritsa([
[self._q[i][k] for k in range(n) if k != j]
for i in range(1, n)
])
d += ((-1) ** j) * self._q[0][j] * minor.determinant()
return d
A = Matritsa([[1, 2], [3, 4]])
B = Matritsa([[5, 6], [7, 8]])
print("1. Asosiy amallar:\n")
print(f" A =")
for q in str(A).split("\n"):
print(f" {q}")
print(f"\n B =")
for q in str(B).split("\n"):
print(f" {q}")
AMALLAR = [
("A + B", lambda: A + B),
("A - B", lambda: A - B),
("A * B", lambda: A * B),
("A @ B", lambda: A @ B),
("A * 2", lambda: A * 2),
("2 * A", lambda: 2 * A),
("A + 10", lambda: A + 10),
("10 + A", lambda: 10 + A),
("10 - A", lambda: 10 - A),
("A / 2", lambda: A / 2),
("-A", lambda: -A),
("A.T", lambda: A.T),
("A ** 2", lambda: A ** 2),
("A ** 0", lambda: A ** 0),
]
print()
for kod, f in AMALLAR:
natija = f()
qatorlar = str(natija).split("\n")
print(f" {kod:<10} = {qatorlar[0]}")
for q in qatorlar[1:]:
print(f" {'':<10} {q}")
print("\n\n2. ⭐ @ va * farqi:\n")
print(f" A * B (elementma-element):")
for q in str(A * B).split("\n"):
print(f" {q}")
print(f" → [1*5, 2*6; 3*7, 4*8]")
print(f"\n A @ B (matritsa ko'paytmasi):")
for q in str(A @ B).split("\n"):
print(f" {q}")
print(f" → [1*5+2*7, 1*6+2*8; 3*5+4*7, 3*6+4*8]")
print(f"""
⭐ PEP 465 (Python 3.5) @ operatorini QO'SHDI.
Sabab: NumPy da ikki xil ko'paytma kerak edi:
* elementma-element (Hadamard)
@ matritsa ko'paytmasi
Oldin: A.dot(B) yoki numpy.matmul(A, B)
Endi: A @ B
""")
print("=== 3. O'lcham xatolari ===\n")
C = Matritsa([[1, 2, 3], [4, 5, 6]])
D = Matritsa([[1, 2], [3, 4], [5, 6]])
print(f" C: {C:olcham}, D: {D:olcham}\n")
for kod, f in [
("C @ D", lambda: C @ D),
("D @ C", lambda: D @ C),
("C @ A", lambda: C @ A),
("C + A", lambda: C + A),
("C.determinant()", lambda: C.determinant()),
("C.iz", lambda: C.iz),
]:
try:
natija = f()
if isinstance(natija, Matritsa):
print(f" {kod:<20} ✅ {natija:olcham}")
else:
print(f" {kod:<20} ✅ {natija}")
except ValueError as e:
print(f" {kod:<20} ❌ ValueError: {e}")
print("\n\n4. Xususiyatlar:\n")
E = Matritsa([[4, -2, 1], [3, 6, -4], [2, 1, 8]])
print(f" E =")
for q in str(E).split("\n"):
print(f" {q}")
print(f"\n E.iz = {E.iz}")
print(f" E.determinant() = {E.determinant()}")
print(f" E.T =")
for q in str(E.T).split("\n"):
print(f" {q}")
print(f"\n Birlik matritsa xossasi:")
I = Matritsa.birlik(3)
print(f" E @ I == E: {E @ I == E} ✅")
print(f" I @ E == E: {I @ E == E} ✅")
print(f"\n Transponirlash xossalari:")
print(f" (A.T).T == A: {(A.T).T == A} ✅")
print(f" (A @ B).T == B.T @ A.T: {(A @ B).T == B.T @ A.T} ✅")
print("\n\n5. Konteyner protokoli:\n")
print(f" A[0] = {A[0]}")
print(f" A[0, 1] = {A[0, 1]}")
print(f" A[1, 0] = {A[1, 0]}")
print(f" len(A) = {len(A)}")
print(f" list(A) = {list(A)}")
print(f" bool(A) = {bool(A)}")
print(f" bool(Matritsa.nol(2)) = {bool(Matritsa.nol(2))}")
print(f"\n Iteratsiya:")
for i, qator in enumerate(A):
print(f" {i}-qator: {qator}")
print("\n\n6. Fibonachchi — matritsa darajasi bilan:\n")
def fib_matritsa(n: int) -> int:
"""⭐ O(log n) — matritsa darajasi orqali."""
if n <= 0:
return 0
M = Matritsa([[1, 1], [1, 0]])
return int((M ** (n - 1))[0, 0])
def fib_oddiy(n: int) -> int:
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a
print(f" {'n':<6} {'Matritsa':<16} {'Oddiy':<16} {'Mos'}")
print(" " + "─" * 48)
for n in [1, 5, 10, 20, 30, 40]:
m = fib_matritsa(n)
o = fib_oddiy(n)
print(f" {n:<6} {m:<16,} {o:<16,} {'✅' if m == o else '❌'}")
print(f"""
⭐ [[1,1],[1,0]]^n = [[F(n+1), F(n)], [F(n), F(n-1)]]
__pow__ tez darajaga ko'tarish ishlatadi:
O(log n) matritsa ko'paytmasi
""")
import timeit
n = 100
t1 = timeit.timeit(lambda: fib_matritsa(n), number=1000)
t2 = timeit.timeit(lambda: fib_oddiy(n), number=1000)
print(f" n={n}, 1000 marta:")
print(f" Matritsa: {t1:.3f}s")
print(f" Oddiy: {t2:.3f}s")
print(f" ⚠️ Kichik n da oddiy tezroq (matritsa ustama xarajati)")Natijaning muhim qismi:
1. Asosiy amallar:
A + B = │ 6 8 │
│ 10 12 │
A * B = │ 5 12 │
│ 21 32 │
A @ B = │ 19 22 │
│ 43 50 │
2. ⭐ @ va * farqi:
A @ B (matritsa ko'paytmasi):
→ [1*5+2*7, 1*6+2*8; 3*5+4*7, 3*6+4*8]
=== 3. O'lcham xatolari ===
C @ D ✅ 2×2
C @ A ❌ ValueError: Ko'paytirib bo'lmaydi: 2×3 @ 2×2
C.determinant() ❌ ValueError: Faqat kvadrat matritsa
6. Fibonachchi — matritsa darajasi bilan:
n Matritsa Oddiy Mos
────────────────────────────────────────────────
40 102,334,155 102,334,155 ✅Nima ko'rsatdi: 2.1, 2.4, 2.7-bo'limlar.
Misol 4 — Amaliy: birlik tizimi
"""Fizik birliklar — turlar aralashuvidan himoya."""
from __future__ import annotations
import math
from dataclasses import dataclass
from decimal import Decimal
from typing import Any
print("=== FIZIK BIRLIKLAR ===\n")
@dataclass(frozen=True, slots=True)
class Olcham:
"""SI asosiy birliklarining darajalari."""
m: int = 0 # metr
kg: int = 0 # kilogramm
s: int = 0 # sekund
A: int = 0 # amper
K: int = 0 # kelvin
def __mul__(self, b: "Olcham") -> "Olcham":
return Olcham(self.m + b.m, self.kg + b.kg, self.s + b.s,
self.A + b.A, self.K + b.K)
def __truediv__(self, b: "Olcham") -> "Olcham":
return Olcham(self.m - b.m, self.kg - b.kg, self.s - b.s,
self.A - b.A, self.K - b.K)
def __pow__(self, n: int) -> "Olcham":
return Olcham(self.m * n, self.kg * n, self.s * n,
self.A * n, self.K * n)
def __bool__(self) -> bool:
return any((self.m, self.kg, self.s, self.A, self.K))
def __str__(self) -> str:
if not self:
return "o'lchamsiz"
surat, maxraj = [], []
for nom, d in (("m", self.m), ("kg", self.kg), ("s", self.s),
("A", self.A), ("K", self.K)):
if d > 0:
surat.append(nom if d == 1 else f"{nom}^{d}")
elif d < 0:
maxraj.append(nom if d == -1 else f"{nom}^{-d}")
s = "·".join(surat) or "1"
return f"{s}/{'·'.join(maxraj)}" if maxraj else s
# ── Standart o'lchamlar ──
OLCHAMSIZ = Olcham()
UZUNLIK = Olcham(m=1)
MASSA = Olcham(kg=1)
VAQT = Olcham(s=1)
TEZLIK = UZUNLIK / VAQT
TEZLANISH = TEZLIK / VAQT
KUCH = MASSA * TEZLANISH
ENERGIYA = KUCH * UZUNLIK
QUVVAT = ENERGIYA / VAQT
BOSIM = KUCH / (UZUNLIK ** 2)
class Miqdor:
"""Birlik bilan son — noto'g'ri amallardan himoya."""
__slots__ = ("qiymat", "olcham")
NOMLAR = {
UZUNLIK: "m", MASSA: "kg", VAQT: "s",
TEZLIK: "m/s", TEZLANISH: "m/s²",
KUCH: "N", ENERGIYA: "J", QUVVAT: "W", BOSIM: "Pa",
Olcham(m=2): "m²", Olcham(m=3): "m³",
}
def __init__(self, qiymat: float, olcham: Olcham = OLCHAMSIZ):
object.__setattr__(self, "qiymat", float(qiymat))
object.__setattr__(self, "olcham", olcham)
def __setattr__(self, n, q):
raise AttributeError("Miqdor o'zgarmas")
# ── Ko'rinish ──
def __repr__(self) -> str:
return f"Miqdor({self.qiymat!r}, {self.olcham!r})"
def __str__(self) -> str:
if not self.olcham:
return f"{self.qiymat:g}"
birlik = self.NOMLAR.get(self.olcham) or str(self.olcham)
return f"{self.qiymat:g} {birlik}"
def __format__(self, spec: str) -> str:
if spec == "si":
return f"{self.qiymat:g} {self.olcham}"
if not spec:
return str(self)
birlik = self.NOMLAR.get(self.olcham) or str(self.olcham)
return f"{format(self.qiymat, spec)} {birlik}".strip()
# ── Taqqoslash ──
def _tekshir(self, b, amal: str) -> "Miqdor":
if isinstance(b, (int, float)):
b = Miqdor(b, OLCHAMSIZ)
if not isinstance(b, Miqdor):
return NotImplemented
if self.olcham != b.olcham:
raise TypeError(
f"O'lchamlar mos emas: [{self.olcham}] {amal} "
f"[{b.olcham}]"
)
return b
def __eq__(self, b) -> bool:
if isinstance(b, (int, float)):
return not self.olcham and self.qiymat == b
if not isinstance(b, Miqdor):
return NotImplemented
return (self.olcham == b.olcham
and math.isclose(self.qiymat, b.qiymat, rel_tol=1e-9))
def __lt__(self, b) -> bool:
b = self._tekshir(b, "<")
if b is NotImplemented:
return NotImplemented
return self.qiymat < b.qiymat
def __le__(self, b) -> bool:
return self < b or self == b
def __gt__(self, b) -> bool:
b = self._tekshir(b, ">")
return NotImplemented if b is NotImplemented else self.qiymat > b.qiymat
def __ge__(self, b) -> bool:
return self > b or self == b
def __hash__(self) -> int:
return hash((round(self.qiymat, 9), self.olcham))
# ── Arifmetika ──
def __add__(self, b) -> "Miqdor":
b = self._tekshir(b, "+")
if b is NotImplemented:
return NotImplemented
return Miqdor(self.qiymat + b.qiymat, self.olcham)
def __radd__(self, b) -> "Miqdor":
# ⭐ sum() hisobni 0 dan boshlaydi: 0 + m(1) → m(1).__radd__(0).
# Oddiy __radd__ = __add__ bo'lsa, 0 "o'lchamsiz" deb olinib,
# [o'lchamsiz] + [m] → TypeError bo'lardi.
if isinstance(b, int) and not isinstance(b, bool) and b == 0:
return self
return self.__add__(b)
def __sub__(self, b) -> "Miqdor":
b = self._tekshir(b, "-")
if b is NotImplemented:
return NotImplemented
return Miqdor(self.qiymat - b.qiymat, self.olcham)
def __rsub__(self, b) -> "Miqdor":
return (-self).__add__(b)
def __mul__(self, b) -> "Miqdor":
"""⭐ O'lchamlar KO'PAYADI."""
if isinstance(b, (int, float)):
return Miqdor(self.qiymat * b, self.olcham)
if not isinstance(b, Miqdor):
return NotImplemented
return Miqdor(self.qiymat * b.qiymat, self.olcham * b.olcham)
__rmul__ = __mul__
def __truediv__(self, b) -> "Miqdor":
"""⭐ O'lchamlar BO'LINADI."""
if isinstance(b, (int, float)):
if b == 0:
raise ZeroDivisionError("Nolga bo'lish")
return Miqdor(self.qiymat / b, self.olcham)
if not isinstance(b, Miqdor):
return NotImplemented
if b.qiymat == 0:
raise ZeroDivisionError("Nolga bo'lish")
return Miqdor(self.qiymat / b.qiymat, self.olcham / b.olcham)
def __rtruediv__(self, b) -> "Miqdor":
if not isinstance(b, (int, float)):
return NotImplemented
if self.qiymat == 0:
raise ZeroDivisionError("Nolga bo'lish")
return Miqdor(b / self.qiymat, OLCHAMSIZ / self.olcham)
def __pow__(self, n) -> "Miqdor":
if not isinstance(n, int):
raise TypeError("Daraja butun son bo'lsin (o'lcham uchun)")
return Miqdor(self.qiymat ** n, self.olcham ** n)
# ── Unar ──
def __neg__(self): return Miqdor(-self.qiymat, self.olcham)
def __pos__(self): return self
def __abs__(self): return Miqdor(abs(self.qiymat), self.olcham)
def __round__(self, n=0): return Miqdor(round(self.qiymat, n), self.olcham)
def __bool__(self): return self.qiymat != 0
def __float__(self) -> float:
if self.olcham:
raise TypeError(
f"O'lchamli miqdorni float ga o'girib bo'lmaydi: "
f"[{self.olcham}]"
)
return self.qiymat
def sqrt(self) -> "Miqdor":
yarim = Olcham(*(d // 2 for d in
(self.olcham.m, self.olcham.kg, self.olcham.s,
self.olcham.A, self.olcham.K)))
if yarim * yarim != self.olcham:
raise ValueError(
f"[{self.olcham}] dan ildiz chiqarib bo'lmaydi"
)
return Miqdor(math.sqrt(self.qiymat), yarim)
# ── Qulaylik funksiyalari ──
def m(q): return Miqdor(q, UZUNLIK)
def kg(q): return Miqdor(q, MASSA)
def s(q): return Miqdor(q, VAQT)
def N(q): return Miqdor(q, KUCH)
print("1. Asosiy amallar:\n")
masofa = m(100)
vaqt = s(9.58)
massa = kg(75)
print(f" masofa = {masofa}")
print(f" vaqt = {vaqt}")
print(f" massa = {massa}\n")
tezlik = masofa / vaqt
print(f" tezlik = masofa / vaqt = {tezlik}")
print(f" SI: {tezlik:si}")
print(f" 2 xona: {tezlik:.2f}")
tezlanish = tezlik / vaqt
kuch = massa * tezlanish
energiya = kuch * masofa
quvvat = energiya / vaqt
print(f"\n tezlanish = tezlik / vaqt = {tezlanish:.3f}")
print(f" kuch = massa * tezlanish = {kuch:.1f}")
print(f" energiya = kuch * masofa = {energiya:.0f}")
print(f" quvvat = energiya / vaqt = {quvvat:.0f}")
print("\n\n2. ⭐ Noto'g'ri amallardan himoya:\n")
XATOLAR = [
("masofa + vaqt", lambda: masofa + vaqt),
("masofa + massa", lambda: masofa + massa),
("masofa - tezlik", lambda: masofa - tezlik),
("masofa < vaqt", lambda: masofa < vaqt),
("float(masofa)", lambda: float(masofa)),
("masofa ** 0.5", lambda: masofa ** 0.5),
("masofa / s(0)", lambda: masofa / s(0)),
]
for kod, f in XATOLAR:
try:
natija = f"⚠️ {f()}"
except (TypeError, ZeroDivisionError, ValueError) as e:
natija = f"✅ {type(e).__name__}: {str(e)[:44]}"
print(f" {kod:<24} {natija}")
print(f"\n ✅ To'g'ri amallar:")
for kod, f in [
("masofa + m(50)", lambda: masofa + m(50)),
("masofa * 2", lambda: masofa * 2),
("2 * masofa", lambda: 2 * masofa),
("masofa / m(2)", lambda: masofa / m(2)),
("masofa ** 2", lambda: masofa ** 2),
("(masofa ** 2).sqrt()", lambda: (masofa ** 2).sqrt()),
("masofa < m(200)", lambda: masofa < m(200)),
("sum([m(1), m(2), m(3)])", lambda: sum([m(1), m(2), m(3)])),
("abs(m(-5))", lambda: abs(m(-5))),
("-masofa", lambda: -masofa),
("100 / s(4)", lambda: 100 / s(4)),
]:
print(f" {kod:<26} → {f()}")
print("\n\n3. ⭐ O'lcham tahlili:\n")
FORMULALAR = [
("Tezlik", masofa / vaqt),
("Tezlanish", masofa / (vaqt ** 2)),
("Kuch", massa * masofa / (vaqt ** 2)),
("Energiya", massa * (masofa ** 2) / (vaqt ** 2)),
("Quvvat", massa * (masofa ** 2) / (vaqt ** 3)),
("Bosim", massa / (masofa * vaqt ** 2)),
("Zichlik", massa / (masofa ** 3)),
("Chastota", Miqdor(1) / vaqt),
]
si_sarlavha = "SI o'lchami"
print(f" {'Kattalik':<14} {'Qiymat':<20} {si_sarlavha}")
print(" " + "─" * 56)
for nom, q in FORMULALAR:
print(f" {nom:<14} {str(q):<20} {q.olcham}")
print("\n\n4. Fizik masala:\n")
print(" Masala: 75 kg massali jism 10 m balandlikdan tushdi.")
print(" Yerga urilish tezligi va energiyasi?\n")
g = Miqdor(9.81, TEZLANISH)
h = m(10)
mm = kg(75)
# v = sqrt(2gh)
v = (Miqdor(2) * g * h).sqrt()
# E = mgh
E = mm * g * h
# t = sqrt(2h/g)
t = (Miqdor(2) * h / g).sqrt()
print(f" g = {g}")
print(f" h = {h}")
print(f" m = {mm}\n")
print(f" v = sqrt(2gh) = {v:.2f}")
print(f" SI: {v:si}")
print(f" E = mgh = {E:.1f}")
print(f" SI: {E:si}")
print(f" t = sqrt(2h/g) = {t:.3f}")
print(f"\n ⭐ Tekshiruv (kinetik energiya):")
Ek = Miqdor(0.5) * mm * (v ** 2)
print(f" Ek = ½mv² = {Ek:.1f}")
print(f" E == Ek: {E == Ek} ✅")
print("\n\n5. Taqqoslash va saralash:\n")
MASOFALAR = [m(100), m(42.195), m(5000), m(1500), m(21.0975)]
print(f" Saralangan: {[str(x) for x in sorted(MASOFALAR)]}")
print(f" Eng uzun: {max(MASOFALAR)}")
print(f" Jami: {sum(MASOFALAR)}")
print(f" O'rtacha: {sum(MASOFALAR) / len(MASOFALAR):.2f}")
print(f"\n Turli o'lchamlarni saralash:")
try:
sorted([m(100), s(50)])
except TypeError as e:
print(f" sorted([m(100), s(50)]) → ✅ TypeError: {str(e)[:44]}")
print(f"\n Hashable:")
print(f" {{m(1), m(1), m(2), s(1)}} → "
f"{len({m(1), m(1), m(2), s(1)})} element")
print(f" ⭐ m(1) va s(1) — turli (o'lcham hashga kiradi)")
print(f"""
⭐ BU SINFDA:
__add__/__radd__ o'lcham TEKSHIRILADI
__mul__/__rmul__ o'lcham KO'PAYADI
__truediv__ o'lcham BO'LINADI
__rtruediv__ 100 / s(4) uchun
__pow__ o'lcham darajaga ko'tariladi
__neg__/__abs__ o'lcham saqlanadi
__float__ ⚠️ o'lchamli bo'lsa TypeError
__eq__/__hash__ o'lcham hisobga olinadi
__lt__ va boshqalar turli o'lcham → TypeError
⭐ NATIJA: Mars Climate Orbiter (1999) tipidagi
xatolar MUMKIN EMAS — birliklar aralashuvi
ish vaqtida darhol aniqlanadi.
""")Natijaning muhim qismi:
1. Asosiy amallar:
tezlik = masofa / vaqt = 10.4384 m/s
SI: 10.4384 m/s
kuch = massa * tezlanish = 81.7 N
energiya = kuch * masofa = 8172 J
2. ⭐ Noto'g'ri amallardan himoya:
masofa + vaqt ✅ TypeError: O'lchamlar mos emas: [m] + [s]
masofa < vaqt ✅ TypeError: O'lchamlar mos emas: [m] < [s]
float(masofa) ✅ TypeError: O'lchamli miqdorni float ga
masofa ** 0.5 ✅ TypeError: Daraja butun son bo'lsin
3. ⭐ O'lcham tahlili:
Kattalik Qiymat SI o'lchami
────────────────────────────────────────────────────────
Tezlik 10.4384 m/s m/s
Kuch 81.7204 N m·kg/s^2
Energiya 8172.04 J m^2·kg/s^2
Bosim 0.00817204 Pa kg/m·s^2
4. Fizik masala:
v = sqrt(2gh) = 14.01 m/s
E = mgh = 7357.5 J
E == Ek: True ✅Nima ko'rsatdi: 2.1, 2.2, 2.4, 2.5, 2.7-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"__add__ yetadi" |
3 * v uchun __rmul__ kerak |
"+= doim __iadd__ chaqiradi" |
Yo'q bo'lsa __add__ ga tushadi |
"__iadd__ None qaytarsa bo'ladi" |
a None bo'ladi |
"__int__ indekslash uchun yetadi" |
__index__ kerak |
"__bool__ int qaytarishi mumkin" |
TypeError |
"Decimal — Real" |
Ataylab ro'yxatga olinmagan |
"sum() faqat __add__ talab qiladi" |
__radd__ ham (0 + x) |
"@ — dekorator belgisi" |
Matritsa ko'paytmasi ham (PEP 465) |
6. Keng tarqalgan xatolar va yechimlari
1. __r*__ unutish
def __mul__(self, n): ... # ⚠️ 3 * v ishlamaydi
__rmul__ = __mul__ # ✅ kommutativ bo'lsa2. Kommutativ bo'lmaganda tartib
def __rsub__(self, b):
return Pul(self.m - b) # ⚠️ teskari!
return Pul(b - self.m) # ✅3. __iadd__ da return yo'q
def __iadd__(self, b):
self.el.extend(b.el) # ⚠️ None
return self # ✅4. NotImplemented o'rniga TypeError
def __add__(self, b):
raise TypeError(...) # ⚠️ teskari sinalmaydi
return NotImplemented # ✅5. __index__ unutish
def __int__(self): ... # ⚠️ lst[x] ishlamaydi
def __index__(self): ... # ✅6. sum() uchun __radd__ yo'q
sum([v1, v2]) # ⚠️ 0 + v1
def __radd__(self, b):
if b == 0: return self # ✅7. __bool__ int qaytaradi
def __bool__(self): return 1 # ❌ TypeError
def __bool__(self): return True # ✅8. __eq__ da float taqqoslash
return self.q == b.q # ⚠️ float aniqligi
return math.isclose(self.q, b.q) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8.12-dars (o'tilgan):
__eq__,NotImplemented - 8.14-dars: konteyner protokoli
- 3-qism: sonlar,
Decimal,Fraction numbers,operator,math— standart kutubxona- NumPy, pandas:
@,__array_ufunc__ pint,astropy.units: haqiqiy birlik kutubxonalari- PEP 465:
@operatori
8. Eng yaxshi amaliyotlar
Har
__op__uchun__rop__yozing. Aks holda3 * vishlamaydi.NotImplementedqaytaring.TypeErrortashlamang — teskari sinalsin.__iadd__dareturn self. Unutish — jimgina xato.__iadd__faqat o'zgaruvchan sinflarda. O'zgarmas bo'lsa —__add__yetadi.__index__qo'shing. Butun son ma'nosini bersa.sum()uchun__radd__da0ni qabul qiling. Yoki boshlang'ich qiymat bering.O'lchamlarni tekshiring. Ma'nosiz amallar
TypeErrorbersin.floattaqqoslashdamath.isclose. Aniq tenglik xavfli.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
1. class A:
def __add__(self, b): return "add"
print(A() + 1, end=" ")
try: print(1 + A())
except TypeError: print("TypeError")
2. class A:
def __radd__(self, b): return "radd"
print(1 + A())
3. lst = [1]; lst2 = lst; lst += [2]; print(lst2)
4. t = (1,); t2 = t; t += (2,); print(t2)
5. class A:
def __init__(self, x): self.x = x
def __iadd__(self, b): self.x += b
a = A(1); a += 2; print(a)
6. class A:
def __int__(self): return 2
try: print([0,1,2][A()])
except TypeError: print("TypeError")
7. class A:
def __len__(self): return 0
print(bool(A()))
8. class A:
def __bool__(self): return False
def __len__(self): return 5
print(bool(A()), len(A()))
9. print(sum([1, 2, 3]), sum([], 10))
10. from decimal import Decimal
from numbers import Real
print(isinstance(Decimal("1"), Real))
11. class A:
def __mul__(self, b): return "mul"
print(A() * 2, end=" ")
try: print(2 * A())
except TypeError: print("TypeError")
12. print(divmod(7, 2), 7 // 2, 7 % 2)Javoblar
add TypeError—__radd__yo'qradd[1, 2]—list.__iadd__joyida(1,)—tuple.__iadd__yo'qNone—__iadd__returnyo'qTypeError—__index__kerakFalseFalse 5—__bool__ustuvor6 10False—Decimalataylab ro'yxatda yo'qmul TypeError(3, 1) 3 1
Vazifa 2: Xatolarni tuzating
1. def __mul__(self, n): return Pul(self.m * n)
2. def __rsub__(self, b): return Pul(self.m - b)
3. def __iadd__(self, b): self.el.extend(b.el)
4. def __add__(self, b):
if not isinstance(b, A): raise TypeError("...")
5. def __int__(self): return int(self.q) # lst[x] kerak
6. def __bool__(self): return len(self.el)
7. sum([Vektor(1,2), Vektor(3,4)])
8. def __eq__(self, b): return self.q == b.q # floatJavoblar
1. __rmul__ = __mul__ qo'shing
2. return Pul(b - self.m)
3. return self qo'shing
4. return NotImplemented
5. __index__ ham qo'shing
6. return len(self.el) > 0 (yoki bool(...))
7. __radd__ qo'shing yoki sum(..., Vektor(0,0))
8. math.isclose(self.q, b.q)Vazifa 3: Kasr sinfi
Yozing:
- Avtomatik qisqartirish (
gcd) +,-,*,/,**va__r*__int,float,Kasrbilan aralash amallar__neg__,__abs__,__round____int__,__float__,__bool__- To'liq taqqoslash (
total_ordering) numbers.Rationalga ro'yxatga olish
Vazifa 4: Polinom sinfi
[1, 2, 3]→1 + 2x + 3x²+,-,*(svertka)__call__— qiymatni hisoblash__truediv__— qoldiq bilan bo'lish (divmod)hosila(),integral()__str__— chiroyli ko'rinish (3x² + 2x + 1)__pow__— butun daraja
Vazifa 5: Bitwise bayroqlar
Bayroqsinfi —&,|,^,~,<<,>>- Barcha
__r*__va__i*__versiyalar __contains__— bayroq bormi__iter__— o'rnatilgan bayroqlar__index__,__int__,__bool__enum.Flagbilan solishtiring
Vazifa 6: Arifmetika tekshiruvchisi
Vosita yozing:
- Sinfda
__op__bor,__rop__yo'qlarni topsin __iadd__dareturnyo'qliginiNotImplementedo'rniga istisno tashlashni__int__bor,__index__yo'qligini__eq__bor,__hash__yo'qligini- Kommutativ bo'lmagan
__r*__xatolarini
Vazifa 7: O'ylash
Nega Python NotImplemented mexanizmini tanladi — nega operator ortiqcha yuklashda oddiy istisno ishlatilmaydi?
Javob
Chunki ikkala operand ham hal qilishga urinishi kerak, va istisno birinchi urinishdayoq to'xtatib qo'yardi.
1. Muammo: kim javobgar?
3 * Vektor(1, 2)Kim bu amalni bajarishi kerak?
int.__mul__(3, v)—intVektorni bilmaydiVektor.__rmul__(v, 3)—Vektorintni biladi
Muammo: int — o'rnatilgan tur, uni o'zgartirib bo'lmaydi. Sizning sinfingiz int dan keyin yozilgan.
2. Istisno bilan bo'lsa
Faraz qilaylik, int.__mul__ TypeError tashlasin:
3 * Vektor(1, 2)
# int.__mul__(3, v) → TypeError
# ⚠️ Python bu yerda to'xtaydi Vektor.__rmul__ hech qachon chaqirilmasdi. Ya'ni:
- O'rnatilgan turlar bilan aralash amal mumkin bo'lmasdi
3 * v,2 + pul,10 / miqdor— hech biri- NumPy, Decimal, Fraction — hech biri ishlamasdi
3. NotImplemented — "men bilmayman, sen sinab ko'r"
class Vektor:
def __mul__(self, b):
if not isinstance(b, (int, float, Vektor)):
return NotImplemented # ⭐ "men bu turni bilmayman"
...Bu — muzokara protokoli:
a + b:
a: "Men b ni bilamanmi?" → yo'q → NotImplemented
b: "Men a ni bilamanmi?" → ha → natija
ikkalasi ham yo'q → TypeError4. Amalda qanday ishlaydi
from decimal import Decimal
from fractions import Fraction
Decimal("1") + Fraction(1, 2)
# Decimal.__add__(Fraction) → NotImplemented
# Fraction.__radd__(Decimal) → NotImplemented
# → TypeError ✅ ataylabFraction(1, 2) + 0.5
# Fraction.__add__(float) → 1.0 ✅ Fraction float ni biladiimport numpy as np
np.array([1, 2]) * 3 # ✅ ndarray.__mul__
3 * np.array([1, 2]) # ✅ ndarray.__rmul__ NumPy int ni o'zgartirmasdan int bilan ishlay oladi — aynan shu mexanizm tufayli.
5. Nega maxsus qiymat, None emas
def __add__(self, b):
return None # ⚠️ chalkash None — haqiqiy qaytarish qiymati bo'lishi mumkin:
class Bosh:
def __add__(self, b):
return None # ataylab None qaytaradi NotImplemented — maxsus singleton, hech qachon oddiy qiymat sifatida ishlatilmaydi:
type(NotImplemented) # <class 'NotImplementedType'>
NotImplemented is NotImplemented # True — yagona nusxa6. NotImplemented — istisno emas
Bu chalkashlik keng tarqalgan:
NotImplemented # ⭐ QIYMAT (singleton)
NotImplementedError # ⭐ ISTISNO (sinf)def __add__(self, b):
return NotImplemented # ✅ qaytariladi
@abstractmethod
def f(self):
raise NotImplementedError # ✅ tashlanadiXato:
def __add__(self, b):
raise NotImplemented # ❌ TypeError: exceptions must derive
# from BaseException7. bool(NotImplemented) — eskirgan
if x == y: # x.__eq__(y) NotImplemented qaytarsa
... Python 3.9 dan bool(NotImplemented) DeprecationWarning beradi:
import warnings
warnings.simplefilter("always")
bool(NotImplemented)
# DeprecationWarning: NotImplemented should not be used in a
# boolean context Sabab: NotImplemented truthy edi, ya'ni:
class A:
def __eq__(self, b): return NotImplemented
if A() == 42: # ⚠️ Python `is` ga tushadi → False
...
# Lekin to'g'ridan-to'g'ri:
n = A().__eq__(42) # NotImplemented
if n: # ⚠️ True! (truthy)
...Kelajakda bu TypeError bo'ladi.
8. Avlod ustuvorligi
Mexanizmda yana bir nozik qoida bor:
class Ota:
def __add__(self, b): return "Ota.__add__"
class Bola(Ota):
def __radd__(self, a): return "Bola.__radd__"
Ota() + Bola() # 'Bola.__radd__' ⭐ avlod birinchiSabab: avlod ota-sinfdan ko'proq biladi. Agar Ota.__add__ birinchi ishlaganda, u Bola ni oddiy Ota deb hisoblardi va avlodning maxsus mantiqini o'tkazib yuborardi.
Shart: avlod __radd__ ni qayta aniqlagan bo'lishi kerak (meros olgan emas).
9. Boshqa tillar
| Til | Yondashuv |
|---|---|
| Python | NotImplemented muzokara |
| C++ | Erkin funksiya: operator+(int, Vec) |
| Ruby | coerce metodi |
| Haskell | Tur sinflari (kompilyatsiya paytida) |
| Rust | impl Mul<Vec> for i32 (trait) |
| Java | Operator ortiqcha yuklash yo'q |
C++ eng moslashuvchan:
Vec operator*(int lhs, const Vec& rhs) { ... }
// ⭐ Sinf TASHQARISIDA — int ni o'zgartirmasdanC++ da operator — erkin funksiya, sinf a'zosi bo'lishi shart emas. Shuning uchun __r*__ kerak emas.
Ruby — coerce:
class Vec
def coerce(other)
[Vec.new(other), self] # ⭐ ikkalasini bir turga keltiradi
end
end
3 * Vec.new(5)
# Integer#* → Vec ni bilmaydi → vec.coerce(3) ni chaqiradi
# → [Vec(3), Vec(5)] → Vec(3) * Vec(5) Ruby yondashuvi eleganter: bitta coerce metodi barcha amallar uchun. Lekin u har doim ham mos kelmaydi (masalan, Matritsa * skalyar da o'girish ma'nosiz).
Rust — trait:
impl Mul<Vec> for i32 { // ⭐ i32 uchun implementatsiya
type Output = Vec;
fn mul(self, rhs: Vec) -> Vec { ... }
}Rust da i32 uchun ham implementatsiya yozish mumkin — chunki trait tizimi buni ruxsat etadi (orphan rule cheklovlari bilan).
10. Xulosa
NotImplemented kerak, chunki:
- O'rnatilgan turlarni o'zgartirib bo'lmaydi —
int.__mul__sizning sinfingizni bilmaydi - Ikkala operand ham urinishi kerak — istisno birinchisida to'xtatardi
- Maxsus qiymat kerak —
Nonehaqiqiy natija bo'lishi mumkin - Xato xabari to'liq bo'lsin — Python ikkalasi rad etgandan keyin aniq
TypeErrorberadi:
Vektor(1,2) + "matn"
# TypeError: unsupported operand type(s) for +: 'Vektor' and 'str'
# ⭐ ikkala tur ham Kompromis: Python C++ ning moslashuvchanligini (erkin operator funksiyalari) tanlamadi — chunki bu nom fazosini murakkablashtiradi. O'rniga u oddiy va bashoratli muzokara protokolini tanladi: har tur o'z metodlarida, NotImplemented — "keyingisiga o't" signali.
Nimani mustahkamlaydi: 2.2, 2.7-bo'limlar.
Xulosa
Bu darsda arifmetika dunder metodlarini o'rgandik.
Eng muhim uch fikr:
Har amal uchun uch metod:
__op__,__rop__,__iop__. Teskari versiya (__radd__,__rmul__) majburiy — chunkiintva boshqa o'rnatilgan turlar sizning sinfingizni bilmaydi vaNotImplementedqaytaradi.3 * vfaqat__rmul__bilan ishlaydi.NotImplemented— muzokara signali, istisno emas.a + bda avvala.__add__(b), uNotImplementedqaytarsab.__radd__(a), ikkalasi ham rad etsa —TypeError.TypeErrorni o'zingiz tashlasangiz, teskari metod hech qachon sinalmaydi.+=—__iadd__, u yo'q bo'lsa__add__.__iadd__obyektni joyida o'zgartiradi vaselfqaytarishi shart (unutish —Nonebilan jimgina xato). Aynan shu sabablistdalst += [x]havolalarga ta'sir qiladi,tupleda esa yo'q.__index__ham alohida e'tibor talab qiladi:__int__indekslash uchun yetarli emas.
Keyingi darsda konteyner protokolini ko'ramiz: __len__, __getitem__, __iter__, __contains__ va o'z konteyner turlaringizni yaratish.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!