Bu makalemizde, Python’da Nesne Tabanlı Programlama OOP(Object-Oriented Programming) nedir ve nasıl yapılır bunu anlatıyor olacağım. Burda unutulmaması gerekir ki Nesne Tabanlı Programlama OOP olarak bilinen bu yazılım paradigması, iş başvuru mülakatlarında ve de yazılım bilginizin olup olmadığı konusu açıldığında soru sorulmaya başvurulan en önemli konulardan biridir. Burada anlatacağımız her anahtar kelime çok önemlidir. Şimdiden dikkatinizi çekmek isterim 😉
Peki, Öyleyse Bu Nesne Tabanlı Programlama Nedir?
Nesne tabanlı programlama, programlama paradigmalarından biridir ve Python gibi birçok programlama dilinde desteklenir. Nesne tabanlı programlama, programların nesnelerin bir araya gelerek ilişkisel bir şekilde çalışmasına dayanır. Her nesne, veri ve işlevselliği içeren bir “sınıf” olarak tanımlanır. Sınıflar, nesnelerin özelliklerini (veri) ve davranışlarını (işlevselliği) tanımlayan “öznitelikler” ve “metodlar” içerir. Bu şekilde, nesne yönelimli programlama, gerçek dünyadaki nesnelerin yapı ve davranışlarını modellemek için kullanılabilir.
Nesne tabanlı programlamanın önemli bir avantajı, programların daha düzenli ve modüler olmasını sağlamasıdır. Programlarınızı sınıflara bölerken, her bir sınıfın kendi işlevselliğine ve verilerine sahip olmasını sağlarsınız. Bu, programı daha kolay anlaşılır, bakımı daha kolay ve hataları daha kolay bulunabilir hale getirir.
Şimdi Nesne tabanlı programlamadaki Docsting, Class(sınıf), object(nesne), İnheritanca(kalıtım), Encapsulation(Kapsülleme), Polymorphism (Çok biçimlilik),Composition(Kompozisyon) gibi kavramlara açıklık getirelim:
1.Docstring (Doküman Dizeleri)
Docstring, Python’da fonksiyonlar, sınıflar veya modüller için belgelendirme metnidir. Bir docstring, ilgili kodun ne yaptığını, nasıl kullanılacağını ve diğer gerekli bilgileri açıklayan açıklamalar içerir. Genellikle üçlü tırnaklar (” ” “) arasına yazılır. Docstring’ler, kodun okunabilirliğini ve anlaşılabilirliğini artırmaya yardımcı olur ve otomatik dokümantasyon araçları tarafından kullanılabilir. İşte bir örnek:
def selamlama(isim): """Bir kişiyi selamlayan bir fonksiyon Args: isim(str): selamlanacak kişinin adı. Returns: str:selamlama metni """ return f"Merhaba, {isim}!" print(selamlama("ibrahim"))
Kodumuzun ekran çıktısı aşağıdaki gibidir:
2. Class (Sınıf) :
Sınıf, nesne tabanlı programlamada temel bir yapıdır ve benzer özelliklere (veri) ve davranışlara (metodlar) sahip nesneleri gruplamak için kullanılır. Sınıflar, nesnelerin taslakları veya şablonları olarak düşünülebilir. Bir sınıfı kullanarak, o sınıfa ait nesneleri oluşturabilirsiniz. Sınıflar, özellikleri ve davranışları tanımlayan öznitelikler ve metodlar içerir. Örneğin:
class Dikdortgen: def __init__(self,kisaKenar,uzunKenar): self.kisaKenar=kisaKenar self.uzunKenar=uzunKenar def AlanBul(self): return self.kisaKenar*self.uzunKenar
Burada kodumuzu inceleyecek olursak, class Dikdortgen: şeklinde sınıf tanımlaması yapılır ve sınıf üzerinden nesne tanımlaması yapılacağı vakit çalışacak ilk fonksiyon olan constructor yapıcı metodu yani def __init__() fonksiyonunu oluşturduk. Burada self anahtar sözcüğü (keyword) __init__ metodu ile gelen ve class içinden türetmiş olduğumuz nesnelere ulaşmamızı sağlayan bir kavramdır. Bu self anahtar kelimesiyle parametre olarak girilen değerleri, kısaKenar ve uzunKenar değişkenlerine attık.
Daha sonra oluşturmuş olduğum AlanBul() Metodu ile alan hesabı yapan işlemi return ile döndermiş olduk.
3.Object (Nesne):
Nesne, bir sınıfın bir örneğidir. Sınıfın belirli özelliklerini ve davranışlarını taşır. Sınıf, nesnelerin bir şablonunu sağlarken, nesne, verileri ve işlevleri gerçekleştiren bir varlık olarak düşünülebilir. Bir sınıftan bir nesne oluşturmak, o nesne için bellekte bir örnekleme yapmak anlamına gelir. Örneğin:
dikdortgenNesnesi=Dikdortgen(5,4) print(" kısa kenarı: {}\n uzun kenarı: {}\n olan dikdörtgenin Alanı :{} ".format(dikdortgenNesnesi.kisaKenar,dikdortgenNesnesi.uzunKenar, dikdortgenNesnesi.AlanBul()))
Burada dikdortgenNesnesi=Dikdortgen(5,4) şeklinde yazılan kodumuzda Dikdortgen sınıfımızdan dikdortgenNesnesi değişkeni ile nesne oluşturmuş oldum.
Sınıf içi özniteliklerine ulaşmak için nesneAdi.degiskenAdi şeklinde kullanılır. Bizim örneğimizde dikdortgenNesnesi.kisaKenar ile kisaKenar bilgisine ulaşmış olurum.
Sınıf içi Metotlara erişim için ise nesneAdi.metotAdi() şeklinde kullanılır. Örneğimizde ise dikdortgenNesnesi.AlanBul() şeklinde metodumuzu çağırmış oldum.
Kodumuzun ekran çıktısı aşağıdaki gibidir:
4.Inheritance (Kalıtım):
Kalıtım, nesne yönelimli programlamada bir sınıfın başka bir sınıftan özelliklerini ve metodlarını devralmasını sağlayan bir mekanizmadır. Bir sınıf, başka bir sınıfın özelliklerini ve davranışlarını miras alarak genişletebilir ve değiştirebilir. Ayrıca Kalıtım, kodun yeniden kullanılabilirliğini artırır ve kod tekrarını önler.
Kullanım olarak Class A: ve Class B adında iki sınıfımız olsun eğer Class A’da metotları ve özenitelikleri B’de tekrar tanımlamadan kullanmak istersem class B (A): şeklinde yazarım Burada amaç reusebility’i yeniden kullanılabilirliği sağlamaktır. Miras alınan class A’ya, Base class yada Super-Class adı verilirken, Miras alan class B sınıfına ise Sub Class ya da Derived Class olarak adlandırılır.
class Hayvan: def __init__(self,isim,renk): self.isim=isim self.renk=renk def konusma(self): print("Hayvan konuşur ") class Kedi(Hayvan): def konusma(self): print(self.renk+" renkli "+self.isim+" Miyaav miyaaav! diyor") kediNesnesi=Kedi("duman","gri") kediNesnesi.konusma()
Burada , “Hayvan” adında bir sınıf tanımladık ve “Kedi” adında bir sınıf oluşturduk. “Kedi” sınıfı, “Hayvan” sınıfından kalıtım alır ve Hayvan sınıfında yazılmış olan “konusma()” metodunu geçersiz kılarak kendi “konuşma()” fonksiyonunu kullanmış olur. Bu sayede, ” Kedi ” nesnesi, ” Hayvan “ sınıfının özelliklerine ve ” konuşma() ” metoduna sahip olurken, kendi davranışını da tanımlayabilir.
5.Composition( Kompozisyon) :
Kompozisyon, bir sınıfın başka bir sınıfı içermesi ve bu sınıfın davranışlarını kullanmasıdır. Kompozisyon, karmaşık yapıları oluşturmak için kullanılır ve sınıflar arasındaki ilişkileri daha esnek hale getirir. Bir sınıfın başka bir sınıfı içermesi, bileşenlerin (sınıfların) birleşmesiyle oluşan bir ilişki anlamına gelir. Örneğin:
class Motor: def Calistir(self): print("motor çalıştı") def Durdur(self): print("Motor durdu") class Araba: def __init__(self): self.motor=Motor() def Calistir(self): print("araba çalıştı ") self.motor.Calistir() def Durdur(self): print("araba durdur") self.motor.Durdur() araba1=Araba() araba1.Calistir() araba1.Durdur()
Yukarıdaki örnekte, “Araba” sınıfı, ” Motor ” sınıfını bir bileşen olarak içerir. Bunu burada Araba sınıfı içerisinde bulunan init fonksiyonunda şu şekilde belirttik self.motor=Motor() böylece “ Araba ” sınıfı, “Calistir()” ve “Durdur()” metodlarını çağırırken, ” Motor ” sınıfının aynı adlı metodlarını kullanır. Bu şekilde, ” Araba ” sınıfı, “Motor” sınıfının davranışını kullanarak daha karmaşık bir işlevsellik sağlar.
Kompozisyon konusunu anladım da hani bir örnek daha olsaydı daha güzel olurdu dediğinizi duyar gibiyim, o zaman okumaya devam 😄
Uygulama Senaryosu
Gerçek bir uygulama olsun Hepimizin malumudur arabayı hareket ettirmeden önce bir motor çalıştırılır ve bir kaç saniye sonra tekerlekler döner ve hareket eder biz de sadece şu üç özelliği kullanarak uygulamamızı yapalım uygulamamızda kurgu olarak şöyle yapalım ilk önce motor çalışsın 2 saniye sonra tekerlekler dönsün ve arada birer saniye olsun tekerlekler arasında ve en sonunda araba harekete geçti desin.
import time class Motor: def __init__(self,beygirGucu,marka): self.beygirGucu=beygirGucu self.marka=marka def calistir(self): print("motor çalıştı") time.sleep(2) class Tekerlekler: def __init__(self,marka,boyut): self.marka=marka self.boyut=boyut def dondur(self): print("Tekerlekler Dönüyor..") time.sleep(1) class Araba: def __init__(self,motor,tekerlekler): self.motor=motor self.tekerlekler=tekerlekler def hareketeGec(self): self.motor.calistir() #self.motor tanımlamasıyla motor sınıfında bulunan calistir() fonksiyonunu çalıştırmışs olduk for tekerlek in self.tekerlekler:#self.tekerlekler yazarak Tekerlekler Sınıfındaki dondur() fonksiyonuna erişebildik tekerlek.dondur() print("araba harekete geçti") motor=Motor(3000,"Toyota") tekerlek1=Tekerlekler("michelin", 14) tekerlek2=Tekerlekler("michelin", 14) tekerlek3=Tekerlekler("michelin", 14) tekerlek4=Tekerlekler("michelin", 14) araba=Araba(motor,[tekerlek1,tekerlek2,tekerlek3,tekerlek4]) araba.hareketeGec()
Yukarıdaki örnekte, “Motor” ve “Tekerlekler” sınıfları, Araba sınıfında kompozisyon ilişkisini temsil eder. Araba sınıfının içinde, Motor ve Tekerlek nesnelerinin örneklerini oluşturarak bu sınıflara erişiriz. Araba’nın “hareketeGec” metodu çağrıldığında, motoru çalıştırır ve tekerlekleri döndürür. Böylece, Araba sınıfının davranışı, içerdiği Motor ve Tekerlek nesnelerinin davranışına dayanır.
Bu örnekte de görüldüğü üzere Kompozisyon, sınıflar arasında güçlü bir bağlantı sağlar ve bir sınıfın başka bir sınıfı içermesine olanak tanır. Böylece, daha karmaşık ve esnek yapılar oluşturabilir.
Bu kodumuzun ekran görüntüsü aşağıdaki gibidir :
Öznur 31 Mayıs 2023
def selamlama(isim):
“””Bir kişiyi selamlayan bir fonksiyon
Args:
isim(str): selamlanacak kişinin adı.
Returns:
str:selamlama metni
“””
return f”Merhaba, {isim}!”
print(selamlama(“öznur”)) merhabalar hocam; ben uzun cod yazmak yerine PRİNT(“MERHBA ÖZNUR “) Yazsak olurmu
Öznur 31 Mayıs 2023
def selamlama(isim):
“””Bir kişiyi selamlayan bir fonksiyon
Args:
isim(str): selamlanacak kişinin adı.
Returns:
str:selamlama metni
“””
return f”Merhaba, {isim}!”
print(selamlama(“öznur”)) merhabalar hocam; ben uzun cod yazmak yerine PRİNT(“MERHBA ÖZNUR “) Yazsak olurmu
İbrahim ATLI 6 Haziran 2023
Merhaba Öznur, elbette olur burada fonksiyon kullanarak daha güzel durmasını sağladık yoksa basit bir şekilde de fonksiyona gerek duymadan, print(“”) ile ekranda görmeyi istediğin şeyi yazabilirsin.