Super fonksiyonunun Multiple Inheritence'de Kullanımı

Herkese merhaba,

super fonksiyonunun tam olarak nasıl çalıştığını anlamaya çalışıyorum. Python’un resmi dokümanlarına baktım ama pek bir şey anladım diyemem. Ama anladıklarımı aktarmak istiyorum.

Şimdi konuyu anlamak için şu şekilde bir kod yazdım.

class A:
    def print_msg(self):
        print("Adana")

    def kebab(self):
        print("kebab from A")

class B:
    def print_msg(self):
        print("İstanbul") 

class D:
    def print_msg(self):
        print("Mersin") 

class C(B, A, D):
    def print_result(self):
        super().kebab()            # B - A - D - object
        super(A, self).kebab()     # D - object 

        super().print_msg()        # B - A - D - object  
        super(B, self).print_msg() # A - D - object
        super(A, self).print_msg() # D - object

example = C()
example.print_result()

C classının mro(method resolution order) 'su B - A - D - object şeklinde.

Anladığım kadarıyla super şu şekilde işliyor. (Örnek üzerinden anlatayım)

super().kebab() da

  1. önce B de kebab methodu var mı diye bakılıyor.
  2. Eğer B de kebab diye bir method yoksa A da kebab methodu var mı diye bakılıyor.
  3. Eğer A da bu method yoksa D ye bakılıyor.
  4. Eğer D de de yoksa object classında kebab diye bir fonksiyon var mı diye bakılıyor.(ki olmadığı için de AttributeError veriyor.)

şimdi bu koddaki hata super(A, self).kebab() dan kaynaklanıyor. Çünkü D classından başlıyor ve sağa doğru ilerliyor.

zaten sanki adı üstünde, method resolution order(kaba bir türkçeyle method çözümleme sırası)

Ben olayı böyle anladım. Sizce olayı doğru bir şekilde anlamış mıyım? Söylemek istediğiniz ek bir şey olursa lütfen belirtin. Şimdiden teşekkür ederim.

Edit:

Aklıma sonradan şu şekilde sorular da takıldı.
super fonksiyonunun ilk parametresi class, ikinci parametresi instance olmak zorunda, neden ikinci parametresi instance olmak zorundadır?

Bu arada şu şekilde denemelerim daha odu.

class A:
    def print_msg(self):
        print("Adana")

    def kebab(self):
        print("kebab from A")

class B:
    def print_msg(self):
        print("İstanbul") 

class D:
    def print_msg(self):
        print("Mersin") 

class X(B, A, D): pass

class C(B, A, D):
    def print_result(self):
        super().kebab()            # B - A - D - object
        # super(A, self).kebab()     # D - object 

        super().print_msg()        # B - A - D - object  
        super(B, self).print_msg() # A - D - object
        super(A, self).print_msg() # D - object

        super(X, X()).kebab()

example = C()
example.print_result()

Bu ornekte mro ya direkt class tan erişebiliyoruz. Yani şöyle

x =X()
print(x.__class__.__mro__)
print(X.__mro__)

Yani instance olmasını gerektiren sebebi anlayamadım. Bana yardımcı olabilir misiniz?

Buraya ve videoya göz atabilirsiniz. Şahsen bu konuları bende bilmiyorum, elimden gelen bu kadar :slight_smile:

----Ekleme----
Kaynak:
https://www.w3schools.com/python/gloss_python_super.asp
Denemesi:

1 Beğeni

İkinci parametresi instance olmak zorunda değil, instance’ın sınıfını da verebilirsiniz.

1 Beğeni

Hocam merhaba, haklısınız, yanılıyormuşum. Öncelikle teşekkürler.

ben aşağıda şöyle bir kod yazdım.

class A:
    def print_msg(self):
        print("Adana")

    def kebab(self):
        print("kebab from A")

class B:
    def print_msg(self):
        print("İstanbul") 

class D:
    def print_msg(self):
        print("Mersin") 

class X(B, A,  D): pass

class C(B, A, D):
    def print_result(self):
        super(X, X()).kebab() # örnek 1
  
example = C()
example.print_result()
 
super(X, X).kebab(X()) # örnek 2
super(X, X()).kebab() # örnek 3
super(X, X).kebab() # örnek 4 (Hata veriyor)

Çıktı da şu şekilde oluyor.

kebab from A
kebab from A
kebab from A
Traceback (most recent call last):
  File "/home/altiparmak/Desktop/a.py", line 24, in <module>
    example.print_result()
  File "/home/altiparmak/Desktop/a.py", line 20, in print_result
    super(X, X).kebab()
TypeError: kebab() missing 1 required positional argument: 'self'

Şimdi buradan anladığım kadarıyla super ile bir methodu kullanırken illaki bir instance a ihtiyaç duyuyoruz.

Bunun nedeni de…

class C():
    def __init__(self):
        self.araba = "Toros"

    def print_result(self): 
        print(self.araba)
        super(X, X()).kebab()

c = C()
c.print_result()

C.print_result()

kodunun hatasız çalışması için self.araba nın tanımlı olması gerekiyor. Ama son satırdaki kodda biz, self.araba değişkenini tanımlamadan langır lungur print_result methodunu çalıştırıyoruz, Bu da hata almamıza neden oluyor.

Eğer durum buysa, eğer super fonksiyonu, instance kullanmasaydı C class ı bir bug olacaktı. O yüzden instance kullanmak zorundayız.

Aynı şekilde bir kod daha

class C():
    def __init__(self, araba):
        self.araba = araba

    def print_result(self): 
        print(self.araba)
        super(X, X()).kebab()

c = C("Toros")
c.print_result()

C.print_result()

Her şey için teşekkürler @EkremDincel hocam.

Konuyu özetle:

super: mro olarak verdiğimiz instance taki mroyu kullanıyor, aldığı birinci parametre ise, mro da nereden başlanacağını gösteriyor.

Olayı doğru anlamış mıyım hocam?

super ile self argümanı alan bir metoda erişip o metodu çağırırken gerekli self argümanını paslamamız lazım. Eğer kebab bir classmethod olsaydı bu hatayı almazdınız:

Evet.

1 Beğeni