Operatorlarni ortiqcha yuklash (Overloading) bilan tanishish
Bilganimizdek, + operatori ikkita sonni qo'shishi, ikkita ro'yxatni birlashtirishi yoki ikkita satrni konkatenatsiya qilishi mumkin.
Ba'zi moslashtirishlar bilan, biz + operatoridan foydalanuvchi belgilagan obyektlar bilan ham ishlashi uchun foydalanishimiz mumkin. Pythonning kontekstga qarab bir xil operatorning turli ma'noga ega bo'lishiga ruxsat beruvchi bu xususiyati operatorni ortiqcha yuklash (operator overloading) deb ataladi.
Pythonda, nomining oldida va orqasida ikkita pastki chiziq (__) ga ega metodlar maxsus ma'noga ega. Masalan, __add__(), __len__() va h.k.
Bu maxsus metodlar muayyan xususiyatlar yoki xatti-harakatlarni amalga oshirish uchun ishlatilishi mumkin.
Keling, ikkita sonni + operatoridan foydalanish o'rniga __add__() metodi yordamida qo'shamiz.
number1 = 5
# number2 = number1 + 6 ga o'xshash
number2 = number1.__add__(6)
print(number2) # 11
Integerlarda __add__() metodidan foydalanish mumkin, chunki:
__add__() metodiga ega.Aslida, + operatori integer va floatlarni qo'shish uchun ichki tomondan __add__() metodini chaqiradi.
Mana Pythonda mavjud bo'lgan ba'zi maxsus funksiyalar:
| Funksiya | Tavsif |
|---|---|
__init__() | Obyektning atributlarini ishga tushiradi. |
__str__() | Obyektning satr ko'rinishini qaytaradi. |
__len__() | Obyektning uzunligini qaytaradi. |
__add__() | Ikkita obyektni qo'shadi. |
__call__() | Klass obyektlarini oddiy funksiya kabi chaqirish imkonini beradi. |
Aytaylik, biz + operatoridan foydalanuvchi belgilagan ikkita obyektni qo'shish uchun foydalanmoqchimiz.
+ operatori ichki tomondan __add__() metodini chaqirgani uchun, agar biz bu metodni klassda amalga oshirsak, o'sha klassning obyektlarini + operatori bilan ishlaydigan qilishimiz mumkin.
Misol: Ikkita koordinatani qo'shish (Ortiqcha yuklashsiz)
Avval keling ikkita koordinatani qo'shuvchi dastur yozamiz (+ operatorini ortiqcha yuklashsiz).
class Point:
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y
def add_points(self, other):
x = self.x + other.x
y = self.y + other.y
return Point(x, y)
p1 = Point(1, 2)
p2 = Point(2, 3)
p3 = p1.add_points(p2)
print((p3.x, p3.y)) # Natija: (3, 5)
Yuqoridagi misolda, biz ikkita nuqtani qo'shish uchun add_points() metodini yaratdik. Bu metodni chaqirish uchun, biz p1.add_points(p2)dan foydalandik.
Keling, xuddi shu kodni ikkita nuqtani qo'shish uchun + operatoridan foydalanib yozamiz.
Misol: Ikkita koordinatani qo'shish (Ortiqcha yuklash bilan)
class Point:
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y
def __add__(self, other):
x = self.x + other.x
y = self.y + other.y
return Point(x, y)
p1 = Point(1, 2)
p2 = Point(2, 3)
# bu operator __add__() metodini chaqiradi
p3 = p1 + p2
print((p3.x, p3.y)) # Natija: (3, 5)
Bu yerda, p1 + p2 kodi __add__(self, other) metodini chaqiradi. self parametri p1ni, other parametri esa p2ni argument sifatida oladi.
Yuqoridagi dasturda, biz + operatoridan ayirish uchun ham osongina foydalanishimiz mumkin edi, masalan shunday:
def __add__(self, other):
x = self.x - other.x
y = self.y - other.y
return Point(x, y)
Endi yuqoridagi koddagi + operatori nuqtalarning ayirish amalini bajaradi. Garchi dastur xatosiz ishlasa-da, siz bundan mutlaqo qochishingiz kerak. Operatorni ortiqcha yuklashda biz har doim operatorlardan mos ravishda foydalanishimiz kerak.
Xuddi shunday, biz boshqa operatorlarni ham ortiqcha yuklashimiz mumkin. Amalga oshirishimiz kerak bo'lgan maxsus funksiya quyida jadvalda keltirilgan.
| Operator | Ifoda | Ichki tomondan |
|---|---|---|
| Qo'shish | p1 + p2 | p1.__add__(p2) |
| Ayirish | p1 - p2 | p1.__sub__(p2) |
| Ko'paytirish | p1 * p2 | p1.__mul__(p2) |
| Daraja | p1 ** p2 | p1.__pow__(p2) |
| Bo'lish | p1 / p2 | p1.__truediv__(p2) |
| Floor Division | p1 // p2 | p1.__floordiv__(p2) |
| Qoldiq (modulo) | p1 % p2 | p1.__mod__(p2) |
| Bitli chapga siljitish | p1 << p2 | p1.__lshift__(p2) |
| Bitli o'ngga siljitish | p1 >> p2 | p1.__rshift__(p2) |
| Bitli AND | p1 & p2 | p1.__and__(p2) |
| Bitli OR | p1 | p2 | p1.__or__(p2) |
| Bitli XOR | p1 ^ p2 | p1.__xor__(p2) |
| Bitli NOT | ~p1 | p1.__invert__() |
Python operatorni ortiqcha yuklashni faqat arifmetik operatorlar bilan cheklamaydi. Biz taqqoslash operatorlarini ham ortiqcha yuklashimiz mumkin.
Mana < operatorini Person klassining ikkita obyektini yoshiga qarab solishtirish uchun qanday ortiqcha yuklash mumkinligiga misol:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
# < operatorini ortiqcha yuklash
def __lt__(self, other):
return self.age < other.age
p1 = Person("Alice", 20)
p2 = Person("Bob", 30)
print(p1 < p2) # True ni chop etadi
print(p2 < p1) # False ni chop etadi
Natija
True
False
Bu yerda, __lt__() ikkita obyektning age atributini solishtirish uchun < operatorini ortiqcha yuklaydi.
__lt__() metodi quyidagini qaytaradi:
True - agar birinchi obyektning yoshi ikkinchi obyektning yoshidan kichik bo'lsaFalse - agar birinchi obyektning yoshi ikkinchi obyektning yoshidan katta bo'lsaXuddi shunday, boshqa taqqoslash operatorlarini ortiqcha yuklash uchun amalga oshirishimiz kerak bo'lgan maxsus funksiyalar quyida jadvalda keltirilgan.
| Operator | Ifoda | Ichki tomondan |
|---|---|---|
| Kichik | p1 < p2 | p1.__lt__(p2) |
| Kichik yoki teng | p1 <= p2 | p1.__le__(p2) |
| Teng | p1 == p2 | p1.__eq__(p2) |
| Teng emas | p1 != p2 | p1.__ne__(p2) |
| Katta | p1 > p2 | p1.__gt__(p2) |
| Katta yoki teng | p1 >= p2 | p1.__ge__(p2) |
Mana operatorni ortiqcha yuklashning ba'zi afzalliklari:
Ko'proq o'qing: Python Classes and Objects, Self in Python, Demystified, Precedence and Associativity of Operators in Python