Bu bölümde genel anlamda magic method yapılarından bahsedeceğiz. Bu magic method yapılarına dunder methods da denir. Double (çift) Underscore (alt tire) ifadelerinin kısaltılmışıdır. Yani aslında şimdiye kadar gördüğümüz __init__, __str__, __repr__ gibi sihirli metotlar da birer dunder metot olarak geçer. Bu metotlar ile oluşturduğumuz nesneleri kolayca, istediğimiz şekilde kontrol edebiliriz.
Python'da int, str, list gibi yapılar aslında birer sınıftır ve bu sınıfların dunder metotları mevcuttur. Bir sürü dunder metodu bulunduğu için şimdi birçoğunu yazacağım, bazılarını da göreceğiz.
__lt__(self, other): Bu ifade, 'less than' kalıbından gelir ve bildiğiniz '<' operatörünü ifade eder.
__gt__(self, other): Bu ifade, 'greater than' kalıbından gelir ve bildiğiniz '>' operatörünü ifade eder.
__le__(self, other): Bu ifade, 'less than or equal' kalıbından gelir ve bildiğiniz '<=' operatörünü ifade eder.
__ge__(self, other): Bu ifade, 'greater than or equal' kalıbından gelir ve bildiğiniz '>=' operatörünü ifade eder.
__ne__(self, other): Bu ifade, 'not equal' kalıbından gelir ve bildiğiniz '!=' operatörünü ifade eder.
__eq__(self, other): Bu ifade, 'equal' kalıbından gelir ve bildiğiniz '==' operatörünü ifade eder.
__add__(self, other): 'Add/Addition' yani 'toplama/ekleme' anlamındadır. '+' operatörünü temsil eder.
__iadd__(self, other): '+=' operatörünü temsil eder.
__sub__(self, other): 'Substraction' yani 'çıkarma' anlamındadır. '-' operatörünü temsil eder.
__isub__(self, other): '-=' operatörünü temsil eder.
__mul__(self, other): 'Multiplication' yani 'çarpma' anlamındadır. '*' operatörünü ifade eder.
__imul__(self, other): '*=' operatörünü temsil eder.
__floordiv__(self, other): 'Floor Division' yani 'bölme' anlamındadır. '//' operatörünü ifade eder. Bu operatör ile yaptığınız bölme işlemleri, ondalıklı sayı döndürmek yerine ondalıklı sayıyı tam sayıya yuvarlayacaktır.
__ifloordiv__(self, other): '//=' operatörünü temsil eder.
__truediv__(self, other): Açılımı, 'True Division' şeklinde, anlamı ise yukarıdaki gibidir. '/' operatörünü ifade eder. Ancak, bunu kullanmanız durumunda bölme işlemi doğru bir şekilde yapılacak ve ondalıklı kısım da gösterilecektir.
__idiv__(self, other): '/=' operatörünü temsil eder.
__mod__(self, other): Bir sayının modunu almaya olanak tanır. '%' operatörünü temsil eder.
__pow__(self, other): Kuvvet alma işlemini gerçekleştirir. '**' operatörünü temsil eder.
__abs__(self): 'Absolute Value' yani 'mutlak değer' anlamındadır. Bu, verilen negatif sayıyı mutlak değer kullanarak pozitif sayıya dönüştürecektir.
__int__(self): int veri tipi ile ilgilidir; int ile alakalı işlemleri baz alır.
__float__(self): float veri tipi ile ilgilidir; float ile alakalı işlemleri baz alır.
__str__(self): string veri tipi ile ilgilidir; string ile alakalı işlemleri baz alır. Detaylar için 'OOP | Bölüm 5' isimli blogu okuyabilirsiniz.
__len__(self): 'Length' yani 'uzunluk' anlamına gelir. Çeşitli kullanım alanlarında üyelerin/karakterlerin uzunluğunu gösterecektir. Genelde listeler için kullanılır.
Bu kadarı yeterli. Eğer daha fazlasını öğrenmek isterseniz dunder methods ile alakalı araştırmalarınızı yapabilirsiniz. Şimdi, bunların ne işe yaradığını anlamaya çalışalım.
Normal şartlarda en basit durumlarda bir toplama işlemini yaparken aşağıdaki gibi yapıyoruz.

Bunu yaparken arka planda aslında biraz önce gördüğümüz __add__ metodu çalışıyor. Hemen deneyelim.

Dikkat edelim; aynı sonucu aldık. Bu noktada aslında int sınıfı içerisindeki __add__ metoduna eriştik ve ona verdiğimiz parametrelerle bu işlemi gerçekleştirdik. Nasıl ki fonksiyon tanımlarken argüman veriyoruz, aynı işlem. Örneğin;
def topla(x, y):
return x + y
topla(3, 4)
dediğimizde bize 3 ve 4'ün yani verdiğimiz argümanların toplamını veriyorsa burada da aynı mantık söz konusu. Bunu şu şekilde gösterebilirim diye düşünüyorum:

Elbette, bu oldukça garip değişken isimlerine sahip ancak bunu hızlıca, örnek olması bakımından verdim. Aslında basit bir print(3 + 4) komutunun arkasında olan şeyleri görün istedim.
Aşağıda, islem.topla() dedik. Bu, int.__add__() gibidir. Burada Python, verilen argümanların int olup olmadığını kontrol ediyor ve __add__ metodunun çağırıldığını görünce bunları topluyor. Başka bir örnek daha yapalım.

Bakın bu sefer de string ifadeler ile işlem yaptık ve yine __add__ metodunu kullandık. Şimdi, aklınıza direkt olarak Type Conversion konusunun gelmiş olması lazım; 'ileride göreceğiz' demiştim ve görüyoruz. Python, yukarıdaki örnekte ifadelerin aynı tipte olup olmadığına bakarak işlem yapıyor. Bu sefer de farklı tiplerde ifadeleri kullanalım ama Type Conversion yapalım.

Normalde surname değişkeninin tuttuğu değer int tipinde. Ancak biz, str(surname) dediğimiz için Python sorun yaratmadı ve işimizi gördü. Biraz önce int sınıfındaki __add__ metoduna eriştik. Şimdi ise str sınıfı içerisindeki __add__ metoduna erişiyoruz. Ayrıca Type Conversion yaptığınızda aslında arka planda Python'a ne kadar yardımcı olduğunuzu görüyorsunuz.
Bu sefer liste ile alakalı bir şeyler yapalım.

Normalde iki listeyi birleştirmek için print(liste1 + liste2) diyorduk ama aslında bunu yaparken arka planda list sınıfının __add__ metodu çalışıyor.
Mesela başka bir dunder metot kullanalım. Örneğin bu iki listenin birbirine eşit olup olmadığını kontrol edelim.

False değer döndü çünkü gerçekten de o iki liste birbirine eşit değil. Ancak dikkat ederseniz bunların uzunlukları aynı. O zaman bunu kontrol edelim mi?

Gerçekten de 'Eşit' sonucu döndü. Bu ifadelerin nasıl çalıştığını öğrendiğimize göre artık bir class tanımlayarak gidelim.

Yukarıda olan biten her şeyi biliyorsunuz. Bunlara ek olarak bir de __add__ metodu ekleyelim ve oradaki iki nesnenin SSD kapasitelerinin toplamını bulalım.

Dikkat ettiyseniz blogun başında bu metotları verirken self ve other şeklinde iki adet argüman verdim. Bu metotların kullanımında other genellikle kullanılır. Bu noktada self.ssd ifadesinin aslında o an erişilen nesne olduğunu biliyorsunuz. other.ssd ise erişilen nesne dışında kalan nesneyi ifade eder. İsterseniz bunu bir test edelim.

Bunu test etmek için ilk önce print(self.ssd), sonra da print(other.ssd) dedim ve self.ssd ifadesinin sonucu 256 olarak geldi. Bu, pc1 nesnesinin SSD değeriydi. other.ssd ifadesinin sonucu ise 512 olarak geldi. Bu da pc2 nesnesinin SSD değeriydi. Dilerseniz __add__ ile ilgili bir örnek daha yapalım. Hem de other ifadesinin mantığını daha iyi kavramış oluruz.

Sakin olalım ve adım adım gidelim. Öncelikle şunu bilmeniz gerekiyor: İki listemiz var ve bu iki liste içerisinde aynı index'e sahip olan değerler toplanacak. Örneğin bu durumda list1 ve list2 için 1 ile 4, 2 ile 5, 3 ile 6 toplanacak.
class ListOperations(list): dedim. Normalde bunun ne olduğunu biliyorsunuz ama parantezler arasındaki 'list' ne oluyor? Bunu yaparak aslında Python'daki list sınıfından miras almış oluyoruz. Yani Inheritence kavramı burada devreye giriyor.
Sonrasında def __add__(self, other): dedik ve aşağı indik. Metodun içerisindeki ilk komut self listesinin other listesine eşit olup olmadığını kontrol ediyor. Yani if list.__len__(self) == list.__len__(other) ifadesi bunu gerçekleştiriyor. İsterseniz bunu direkt olarak if len(self) == len(other) şeklinde de yazabilirsiniz; ben görmeniz için yaptım. Listelerin eşit uzunlukta olması, aynı index'te bulunan elemanların toplanması için gereklidir.
Bu koşul ile listelerin uzunluğunu kontrol ediyoruz ve eğer listelerin uzunluğu eşitse result = [] ifadesi ile boş bir liste oluşturuyoruz. Sonrasında bir for döngüsü kullanarak listenin elemanlarını teker teker kontrol ediyoruz. Bu noktada bu kontrolün range(len(self)) kadar olması lazım ki hata almayalım.
Bu kontrol durumu sürdükçe yani len(self) boyunca result.append(self[number] + other[number]) diyerek bu iki listenin elemanlarını topluyorum ve result isimli listeye koyuyorum.
Eğer bu iki listenin uzunluğu birbirine eşit değilse "Listeler eşit uzunlukta olmadığından işlem yapılamıyor" mesajını veriyoruz. Eğer eşit ise return result diyoruz ve sonucu ekrana veriyoruz.
Çıktı kısmına baktığınızda ise sonucun [5, 7, 9] şeklinde, doğru bir şekilde geldiğini göreceksinizdir. Bir de listelerden birinin uzunluğunu değiştirelim ve sonuca bakalım.

list1 nesnesine bir eleman daha ekledim ve kodumun düzgün çalıştığını görüyorum.
İsterseniz bir çarpma işlemi de yapabiliriz.

Değiştirdiğim kısımları kırmızı renkli kutucuk ve dairelerle belirttim. list1 ve list2 içerisindeki elemanlar için aynı index'e denk gelenler çarpıldı ve sonuç ekrana verildi.
Diğer metotları kendiniz inceleyebilir, bunları bozabilir, bin türlü hata ile karşılaşabilirsiniz. Sorunlar, sürecin bir parçasıdır. Bunu, OOP konusu gerçekten biraz zor olduğu için söylüyorum. Sadece sakin olun ve çalışmaya devam edin. Sevgiler.
Yayınlanma Tarihi: 2022-12-27 18:07:49
Son Düzenleme Tarihi: 2022-12-30 15:19:56