Kalıtım ve Polimorfizm
Kalıtım ve polimorfizm - bu Python'da çok önemli bir kavramdır. Öğrenmek istiyorsan daha iyi anlamalısın.
Miras
Nesne Yönelimli Programlamanın en önemli avantajlarından biri yeniden kullanımdır. Kalıtım, aynı şeyi başarmanın mekanizmalarından biridir. Miras, programcının önce bir genel veya temel sınıf oluşturmasına ve daha sonra bunu daha özel bir sınıfa genişletmesine olanak tanır. Programcının daha iyi kod yazmasını sağlar.
Devralmayı kullanarak, temel sınıfınızda bulunan tüm veri alanlarını ve yöntemleri kullanabilir veya devralabilirsiniz. Daha sonra kendi yöntemlerinizi ve veri alanlarınızı ekleyebilirsiniz, böylece miras, kodu sıfırdan yeniden yazmak yerine düzenlemenin bir yolunu sağlar.
Nesne yönelimli terminolojide, X sınıfı Y sınıfını genişlettiğinde, Y'ye süper / üst / temel sınıf ve X'e alt sınıf / alt / türetilmiş sınıf denir. Burada dikkat edilmesi gereken bir nokta, yalnızca özel olmayan veri alanlarının ve yöntemin alt sınıflar tarafından erişilebilir olmasıdır. Özel veri alanlarına ve yöntemlerine yalnızca sınıf içinden erişilebilir.
türetilmiş bir sınıf oluşturmak için sözdizimi -
class BaseClass:
Body of base class
class DerivedClass(BaseClass):
Body of derived class
Öznitelikleri Devralma
Şimdi aşağıdaki örneğe bakın -
Çıktı
Önce Date adında bir sınıf oluşturduk ve nesneyi bir argüman olarak ilettik, burada nesne Python tarafından sağlanan yerleşik bir sınıftır. Daha sonra time adında başka bir sınıf oluşturduk ve argüman olarak Date sınıfını çağırdık. Bu çağrı aracılığıyla, Time sınıfındaki Date sınıfının tüm verilerine ve özniteliklerine erişebiliriz. Bundan dolayı, daha önce oluşturduğumuz Time sınıfı tm nesnesinden get_date yöntemini almaya çalıştığımızda mümkün.
Object.Attribute Arama Hiyerarşisi
- Örnek
- Sınıf
- Bu sınıfın miras aldığı herhangi bir sınıf
Kalıtım Örnekleri
Miras örneğine yakından bakalım -
Örneklere katılmak için birkaç sınıf oluşturalım -
- Hayvan - Sınıf bir hayvanı simüle eder
- Kedi - Hayvanın Alt Sınıfı
- Köpek - Hayvanın Alt Sınıfı
Python'da, bir nesne (örnek) oluşturmak ve özniteliklerin değerini atamak için kullanılan sınıfın yapıcısı.
Alt sınıfların oluşturucusu, her zaman üst sınıftaki özniteliklerin değerini başlatmak için bir üst sınıf yapıcısına çağrılır, ardından öznitelikleri için değer atamaya başlar.
Çıktı
Yukarıdaki örnekte, üst sınıfa koyduğumuz komut özniteliklerini veya yöntemlerini görüyoruz, böylece tüm alt sınıflar veya alt sınıflar, bu özelliği üst sınıftan miras alacaktır.
Bir alt sınıf, yöntemleri veya verileri başka bir alt sınıftan miras almaya çalışırsa, Dog sınıfı bu cat sınıfından swatstring () yöntemlerini çağırmaya çalıştığında gördüğümüz gibi bir hatayla karşılaşacaktır, bir hata atar (bizim durumumuzda AttributeError gibi).
Polimorfizm ("BİRÇOK ŞEKİL")
Çok biçimlilik, Python'da sınıflar veya alt sınıflar arasında yaygın olarak adlandırılmış yöntemler bulunduğunda kullanılan sınıf tanımının önemli bir özelliğidir. Bu, işlevlerin farklı zamanlarda farklı türlerdeki varlıkları kullanmasına izin verir. Bu nedenle, esneklik ve gevşek bağlantı sağlar, böylece kod zaman içinde genişletilebilir ve kolayca korunabilir.
Bu, işlevlerin bu çok biçimli sınıflardan herhangi birinin nesnelerini, sınıflar arasındaki ayrımların farkında olmaları gerekmeden kullanmalarına izin verir.
Polimorfizm kalıtım yoluyla, alt sınıfların temel sınıf yöntemlerini kullanarak veya onları geçersiz kılarak gerçekleştirilebilir.
Polimorfizm kavramını önceki kalıtım örneğimizle anlayalım ve her iki alt sınıfta da show_affection adlı ortak bir yöntem ekleyelim -
Görebildiğimiz örnekten, farklı türdeki nesnenin aynı şekilde veya daha spesifik olarak iki veya daha fazla sınıfın aynı adı taşıyan yöntemle veya ortak arayüzle ele alınabileceği bir tasarıma atıfta bulunur çünkü aynı yöntem (aşağıdaki örnekte show_affection) her iki tür nesne ile çağrılır.
Çıktı
Yani, tüm hayvanlar şefkat gösterir (show_affection), ancak farklı şekilde yaparlar. "Şov_etki" davranışları, hayvana bağlı olarak farklı şekilde hareket etmesi anlamında polimorfiktir. Dolayısıyla, soyut "hayvan" kavramı aslında "şov_sevgi" değildir, ancak belirli hayvanlar (köpekler ve kediler gibi) somut bir "şov_sevişme" eylemine sahiptir.
Python'un kendisi polimorfik sınıflara sahiptir. Örneğin, len () işlevi birden çok nesneyle kullanılabilir ve tümü giriş parametresine göre doğru çıktıyı döndürür.
Geçersiz kılma
Python'da, bir alt sınıf, üst sınıfın bir yöntemini geçersiz kılan bir yöntem içerdiğinde, üst sınıf yöntemini çağırarak da çağırabilirsiniz.
Self.method yerine Super (Subclass, self).
Misal
class Thought(object):
def __init__(self):
pass
def message(self):
print("Thought, always come and go")
class Advice(Thought):
def __init__(self):
super(Advice, self).__init__()
def message(self):
print('Warning: Risk is always involved when you are dealing with market!')
Yapıcıyı Devralma
Önceki kalıtım örneğimizden bakarsak, __init__ üst sınıfta üst sınıfta yer alıyordu çünkü alt sınıf köpek veya kedinin içinde __init__ yöntemi yoktu. Python, hayvan sınıfında __init__ öğesini bulmak için kalıtım niteliği aramasını kullandı. Çocuk sınıfını oluşturduğumuzda, ilk olarak köpek sınıfında __init__ yöntemine bakacak, sonra onu bulamadı sonra Animal sınıfına baktı ve orada buldu ve orada çağırdı. Sınıf tasarımımız karmaşık hale geldikçe, bir örneği önce ana sınıf yapıcısı ve ardından alt sınıf kurucusu aracılığıyla işleyerek başlatmak isteyebiliriz.
Çıktı
Yukarıdaki örnekte, tüm hayvanların bir adı ve tüm köpeklerin belirli bir cinsi vardır. Super ile ebeveyn sınıf yapıcı adını verdik. Öyleyse köpeğin kendi __init__'si vardır, ancak olan ilk şey süper diyoruz. Super işlevi yerleşiktir ve bir sınıfı süper sınıfıyla veya ana sınıfıyla ilişkilendirmek için tasarlanmıştır.
Bu durumda, süper köpek sınıfını alın ve köpek örneğini burada kurucu __init__ dediğimiz yönteme geçirin deriz. Başka bir deyişle, köpek nesnesiyle Animal __init__ ebeveyn sınıfına diyoruz. Köpek örneğiyle neden sadece Animal __init__ demeyeceğimizi sorabilirsiniz, bunu yapabilirdik ama gelecekte bir ara hayvan sınıfının adı değişecek olursa. Ya sınıf hiyerarşisini yeniden düzenlemek istersek, köpek başka bir sınıftan miras kalmıştır. Bu durumda süper kullanmak, işleri modüler tutmamızı ve değiştirmesi ve bakımı kolay hale getirmemizi sağlar.
Dolayısıyla bu örnekte genel __init__ işlevini daha özel işlevlerle birleştirebiliriz. Bu bize, ortak işlevselliği, kod tekrarını ortadan kaldırabilen ve sınıfı birbiriyle sistemin genel tasarımını yansıtacak şekilde ilişkilendirebilen belirli işlevlerden ayırma fırsatı verir.
Sonuç
__init__ diğer yöntemler gibidir; miras alınabilir
Bir sınıfın __init__ kurucusu yoksa, Python bir tane bulup bulamayacağını görmek için üst sınıfını kontrol eder.
Python bulduğu anda onu arar ve aramayı bırakır
Üst sınıfta yöntemleri çağırmak için super () işlevini kullanabiliriz.
Kendi sınıfımızın yanı sıra ebeveynde de başlatmak isteyebiliriz.
Çoklu Kalıtım ve Arama Ağacı
Adından da anlaşılacağı gibi, çoklu kalıtım, bir sınıfın birden fazla sınıftan miras aldığı zamandır.
Örneğin, bir çocuk kişilik özelliklerini her iki ebeveynden (Anne ve Baba) miras alır.
Python Çoklu Kalıtım Sözdizimi
Bir sınıfın birden çok ebeveyn sınıfından miras almasını sağlamak için, bu sınıfların adlarını parantezler içinde türetilmiş sınıfa tanımlarken yazıyoruz. Bu isimleri virgülle ayırıyoruz.
Aşağıda bunun bir örneği var -
>>> class Mother:
pass
>>> class Father:
pass
>>> class Child(Mother, Father):
pass
>>> issubclass(Child, Mother) and issubclass(Child, Father)
True
Çoklu miras, iki veya daha fazla sınıftan miras alma yeteneğini ifade eder. Karmaşıklık, çocuk ebeveynden miras aldıkça ve ebeveynler büyükbaba sınıfından miras aldıkça ortaya çıkar. Python, bir nesneden okunması istenen özellikleri arayan miras alan bir ağaca tırmanır. Örneği, sınıf içinde, sonra ebeveyn sınıfı ve son olarak büyükbaba sınıfından kontrol edecektir. Şimdi, sınıfların hangi sırada aranacağı sorusu ortaya çıkıyor - önce nefes mi yoksa önce derinlik mi? Varsayılan olarak, Python önce derinlik ile gider.
Bu nedenle, aşağıdaki diyagramda Python, A sınıfında ilk olarak dothis () yöntemini arar. Bu nedenle, aşağıdaki örnekteki yöntem çözümleme sırası şöyle olacaktır:
Mro- D→B→A→C
Aşağıdaki çoklu kalıtım diyagramına bakın -
Bir Python'un "mro" özelliğini anlamak için bir örnek üzerinden geçelim.
Çıktı
Örnek 3
"Elmas şekli" çoklu kalıtımın başka bir örneğini ele alalım.
Yukarıdaki diyagram belirsiz olarak değerlendirilecektir. Önceki örneğimizden "yöntem çözünürlük sırasını" anlamaktan .ie mro, D → B → A → C → A olacaktır, ancak değil. C'den ikinci A'yı alırken, Python önceki A'yı görmezden gelecektir, bu nedenle mro bu durumda D → B → C → A olacaktır.
Yukarıdaki diyagrama göre bir örnek oluşturalım -
Çıktı
Yukarıdaki çıktıyı anlamanın basit kuralı, aynı sınıf yöntem çözümleme sırasında görünürse, bu sınıfın önceki görünümleri yöntem çözümleme sırasından kaldırılacaktır.
Sonuç olarak -
Herhangi bir sınıf birden fazla sınıftan miras alabilir
Python, miras alan sınıfları ararken normalde "önce derinlik" sıralaması kullanır.
Ancak iki sınıf aynı sınıftan miras aldığında, Python bu sınıfın mro'dan ilk görünümünü ortadan kaldırır.
Dekoratörler, Statik ve Sınıf Yöntemleri
Fonksiyonlar (veya yöntemler) def deyimiyle oluşturulur.
Yöntemler, yöntemin ilk bağımsız değişkeninin örnek nesne olduğu bir nokta dışında, bir işlevle tamamen aynı şekilde çalışır.
Yöntemleri nasıl davrandıklarına göre sınıflandırabiliriz.
Simple method- bir sınıfın dışında tanımlanır. Bu işlev, örnek argümanını besleyerek sınıf özelliklerine erişebilir:
def outside_func(():
Instance method -
def func(self,)
Class method - sınıf niteliklerini kullanmamız gerekirse
@classmethod
def cfunc(cls,)
Static method - sınıf hakkında herhangi bir bilgi yok
@staticmethod
def sfoo()
Şimdiye kadar örnek yöntemini gördük, şimdi diğer iki yöntem hakkında biraz fikir edinme zamanı.
Sınıf Yöntemi
@Classmethod dekoratörü, çağrıldığı sınıfı veya ilk argüman olarak çağrıldığı örneğin sınıfını geçiren yerleşik bir işlev dekoratörüdür. Bu değerlendirmenin sonucu, işlev tanımınızı gölgeler.
sözdizimi
class C(object):
@classmethod
def fun(cls, arg1, arg2, ...):
....
fun: function that needs to be converted into a class method
returns: a class method for function
Bu cls argümanına erişimleri var, nesne örneğinin durumunu değiştiremez. Bu, kendine erişim gerektirir.
Sınıfın nesnesine değil sınıfa bağlıdır.
Sınıf yöntemleri, sınıfın tüm örneklerinde geçerli olan sınıf durumunu yine de değiştirebilir.
Statik Yöntem
Statik bir yöntem ne self ne de cls (sınıf) parametresi almaz, ancak rastgele sayıda diğer parametreleri kabul etmekte serbesttir.
syntax
class C(object):
@staticmethod
def fun(arg1, arg2, ...):
...
returns: a static method for function funself.
- Statik bir yöntem, nesne durumunu veya sınıf durumunu değiştiremez.
- Hangi verilere erişebilecekleri kısıtlanmıştır.
Ne zaman kullanılmalı
Fabrika yöntemlerini oluşturmak için genellikle sınıf yöntemini kullanırız. Fabrika yöntemleri, farklı kullanım durumları için sınıf nesnesini (bir kurucuya benzer) döndürür.
Fayda fonksiyonları oluşturmak için genellikle statik yöntemler kullanırız.