6.1 Sehrli metodlar
Python-da operatorların overloading-i, daxili operatorların (məsələn, +
, -
, *
, /
) davranışını istifadəçi sinifləri üçün təyin etməyə və ya dəyişdirməyə imkan verir. Bu, xüsusi metodlar vasitəsilə həyata keçirilir və həmin metodlara sehrli metodlar deyilir.
Məsələn, öz sinfinizdə müqayisə operatorlarını overload edə bilərsiniz:
Operator | Alt xəttsiz metod | Metodun imzası |
---|---|---|
== | eq() |
__eq__(self, other) |
!= | ne() |
__ne__(self, other) |
< | lt() |
__lt__(self, other) |
<= | le() |
__le__(self, other) |
> | gt() |
__gt__(self, other) |
>= | ge() |
__ge__(self, other) |
Tutaq ki, siz öz sinfinizi yazmısınız və istəyirsiniz ki, həmin sinfin obyektləri sizin istədiyiniz şəkildə müqayisə edilsin. Bunun üçün sadəcə sinfinizdə «__eq__»
metodunu implement etməlisiniz, və Python hər dəfə sizin sinif obyektlərinizi müqayisə edərkən həmin metodu çağıracaq.
Nümunə:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
return self.x == other.x and self.y == other.y
# İstifadə
v1 = Vector(2, 3)
v2 = Vector(2, 3)
v3 = Vector(4, 5)
print(v1 == v2) # Çap edəcək: True
print(v1 == v3) # Çap edəcək: False
Hər dəfə obyektlərinizi müqayisə edərkən Python yoxlayır ki, onların «__eq__»
funksiyası implement edilibmi. Əgər varsa, onu çağırır. Yoxdursa, onda sadəcə obyektlərin referanslarını müqayisə edir.
Əslində yuxarıdakı nümunədə yazılan belədir (amma metodu yoxlamağı da əlavə etmək lazımdır):
# İstifadə
v1 = Vector(2, 3)
v2 = Vector(2, 3)
v3 = Vector(4, 5)
print(v1.__eq__(v2)) # Çap edəcək: True
print(v1.__eq__(v3)) # Çap edəcək: False
6.2 Bütün operatorların siyahısı
Ümumilikdə yenidən yükləmə üçün 6 operator qrup mövcuddur.
Riyazi operatorlar:
Operator | Altdan xətsiz metod | Metodun imzası |
---|---|---|
+ | add |
__add__(self, other) |
- | sub |
__sub__(self, other) |
* | mul |
__mul__(self, other) |
/ | truediv |
__truediv__(self, other) |
// | floordiv |
__floordiv__(self, other) |
% | mod |
__mod__(self, other) |
** | pow |
__pow__(self, other) |
Müqayisə operatorları:
Operator | Altdan xətsiz metod | Metodun imzası |
---|---|---|
== | eq |
__eq__(self, other) |
!= | ne |
__ne__(self, other) |
< | lt |
__lt__(self, other) |
<= | le |
__le__(self, other) |
> | gt |
__gt__(self, other) |
>= | ge |
__ge__(self, other) |
Məntiqi operatorlar:
Operator | Altdan xətsiz metod | Metodun imzası |
---|---|---|
& | and |
__and__(self, other) |
| | or |
__or__(self, other) |
^ | xor |
__xor__(self, other) |
~ | invert |
__invert__(self) |
İndeksasiya və dilim operatorları:
Operator | Metod |
---|---|
obj[key] | __getitem__(self, key) |
obj[key] = value | __setitem__(self, key, value) |
del obj[key] | __delitem__(self, key) |
Unar operatorlar:
Operator | Metod |
---|---|
- | __neg__(self) |
+ | __pos__(self) |
abs() | __abs__(self) |
~ | __invert__(self) |
Təyinetmə operatorları:
Operator | Metod |
---|---|
+= | __iadd__(self, other) |
-= | __isub__(self, other) |
*= | __imul__(self, other) |
/= | __itruediv__(self, other) |
//= | __ifloordiv__(self, other) |
%= | __imod__(self, other) |
**= | __ipow__(self, other) |
Ola bilsin ki, buna görə Python bu qədər yavaşdır – hər dəfə operatorun icrasından əvvəl o, sinifdə və onun bütün ana siniflərində uyğun funksiyanı axtarır. Amma bunun sayəsində dünyada ən yığcam kodu yazmaq mümkündür :)
6.3 İndeksləmə Operatoru
Obyektlərin müqayisə edilməsi və ya çoxluqların çıxarılması məsələləri müəyyən mənada aydındır. Əgər məntiqi və ya riyazi əməliyyatların tətbiq olunduğu bir sinif yazdıqda bunu özünüz də başa düşəcəksiniz.
Sizə maraqlı bir nümunədən danışmaq istəyirəm – yəni indeksləmə operatoru. Gəlin dərhal nümunə koduna baxaq:
class CustomList:
def __init__(self, data):
self.data = data
def __getitem__(self, index):
return self.data[index]
def __setitem__(self, index, value):
self.data[index] = value
def __delitem__(self, index):
del self.data[index]
def __repr__(self):
return repr(self.data)
# İstifadə
c_list = CustomList([1, 2, 3, 4, 5])
print(c_list[1]) # Çıxış: 2
c_list[1] = 10
print(c_list) # Çıxış: [1, 10, 3, 4, 5]
del c_list[1]
print(c_list) # Çıxış: [1, 3, 4, 5]
Burada üç əməliyyatın nümunəsini görürük:
Məlumatların indeks vasitəsilə oxunması
Məlumatların indeks vasitəsilə yazılması
Hətta məlumatların indeks vasitəsilə silinməsi
Amma məlumatların içəridə siyahı formasında saxlanılması vacib deyil. Və ya indeks mütləq rəqəm olmaq məcburiyyətində deyil. Məsələn, dictionary
(sözlük) sinifi bu cür reallaşdırılıb.
SuperList
Yaradaq
list
sinifini xatırlayırsınız? Ona ancaq mövcud indekslərə elementlər təyin etmək mümkündür. Gəlin öz sinifimizi yaradaq, ona SuperList
adını verək; bu sinifin elementlərinə istənilən indekslə müraciət etmək mümkün olacaq:
Əgər indeks < 0-dırsa, elementi əvvələ yerləşdirəcəyik
Əgər indeks >= len-dirsə, elementi sona əlavə edəcəyik
Qalan hallarda sadəcə elementi qaytaracağıq
Nümunə:
class SuperList(list):
def __init__(self, value):
super().__init__(value)
def __setitem__(self, index, value):
if index >= len(self):
super().append(value)
elif index < 0:
super().insert(0, value)
else:
super().__setitem__(index, value)
lst = SuperList([1, 2, 3])
lst[200] = 100
lst[-200] = 99
print(lst) # [99, 1, 2, 3, 100]
Beləliklə, indekslərin yenidən yüklənməsi əla bir funksionallıqdır və praktiki istifadəsini şiddətlə tövsiyə edirəm. Bu günlük bu qədər.
GO TO FULL VERSION