Python ile Nesne Yönelimli Programlama: Adım Adım OOP
Python'da sınıf, kalıtım, kompozisyon, özel metotlar ve veri sınıfları ile nesne yönelimli programlamayı adım adım, örneklerle ve sık hatalarla öğrenin.
Nesne yönelimli programlama neden öğrenilir?
Nesne yönelimli programlama (OOP), kodu verileri ve onları işleyen davranışları birlikte tutan nesneler etrafında düzenleme yaklaşımıdır. Betik halinde yazılan kod küçük işlerde yeterlidir; ancak proje büyüdükçe aynı verilere dokunan işlevler dağılır, değişiklik yapmak riskli hale gelir. OOP bu karmaşıklığı sorumlulukları sınıflara ayırarak yönetilebilir kılar.
Python'da OOP zorunlu değildir, her şeyi nesne olarak ele alan esnek bir dil olduğu için ihtiyaç duyulduğunda kullanılır. Kütüphane yazarken, bir veri modeli kurarken, ortak kod içinde çalışan bir ekipte ya da test edilebilir bir uygulama kurarken sınıf yapısı en çok fayda sağlar.
Sınıf, nesne ve kapsülleme
Sınıf, bir şeyin planıdır; nesne ise bu plandan üretilen somut örnektir. Örneğin bir Müşteri sınıfı; ad, e-posta gibi veriler ile bunlar üzerinde çalışan davranışları tanımlar. Her müşteri bu sınıftan üretilen ayrı bir nesnedir.
Kapsülleme, nesnenin iç durumunu dışarıdan doğrudan değiştirilmeye karşı korumak ve değişimi kontrollü yöntemlerden geçirmektir. Python'da bu, katı bir erişim engelinden çok bir sözleşme olarak çalışır: alt çizgiyle başlayan adlar "iç kullanım" anlamına gelir. Özellik (property) kullanarak bir alanı dışarıdan sıradan değer gibi okutup, atama sırasında doğrulama yapmak ise yaygın bir tekniktir.
Küçük bir örnek: bir Hesap sınıfında bakiye alanı doğrudan değiştirilebilir olursa, eksi bakiyeye düşüren bir atama kodun herhangi bir yerinden yapılabilir. Bakiyeyi yalnızca para yatırma ve çekme yöntemleri üzerinden değiştirmek, kuralı (bakiye yetersizse çekim reddedilir) tek yerde toplar. Kapsülleme, bu tür kuralların dağılmasını önleyen temel araçtır.
Kalıtım mı, kompozisyon mu?
Kalıtım, bir sınıfın başka bir sınıfın özelliklerini devralmasıdır. "Her ... bir ..." ilişkisi gerçekten geçerliyse uygundur: örneğin her Kedi bir Hayvandır. Ancak kalıtım sıkı bir bağ kurar; üst sınıftaki değişiklik tüm alt sınıfları etkiler.
Kompozisyonda ise bir nesne, ihtiyaç duyduğu başka nesneleri içinde barındırır: "bir ... vardır" ilişkisi. Bir Sipariş nesnesi, bir Ödeme nesnesine sahiptir. Pratikte güvenli kural, davranışı yeniden kullanmak için kalıtım yerine kompozisyonu tercih etmek, kalıtımı ise gerçek bir tür ilişkisi olduğunda kullanmaktır. Çoklu kalıtımda hangi sınıfın metodunun çalışacağını belirleyen metot çözüm sırasını (MRO) anlamak, beklenmedik davranışları önler.
Kalıtımda sık yapılan bir karar hatası, yalnızca kod paylaşmak için kalıtım kurmaktır. Örneğin Kullanıcı sınıfından Rapor sınıfı türetmek, ikisi arasında tür ilişkisi olmadığı halde yalnızca ortak bir kaydetme metodu paylaşmak içindir; bunun yerine kaydetmeyi ayrı bir nesneye verip iki sınıfta kullanmak bağımlılığı gevşetir.
Özel metotlar, veri sınıfları ve tipler
Python'un veri modeli, çift alt çizgiyle yazılan özel metotlarla nesnelerinizin yerleşik davranışlara uymasını sağlar. Nesnenin metin gösterimi, eşitlik karşılaştırması, sıralanması, uzunluğu ya da döngüde gezilmesi gibi davranışlar bu metotlarla tanımlanır. Böylece kendi sınıfınız dilin doğal sözdizimiyle kullanılabilir.
Yalnızca veri taşıyan sınıflar için veri sınıfları (dataclass), standart kalıp kodu, yani kurucu, gösterim ve karşılaştırma metotlarını sizin yerinize üretir. Tip ipuçları ekleyerek kodun okunabilirliğini artırabilir, doğrulama kütüphaneleriyle girdi verisinin beklenen biçimde olup olmadığını kontrol edebilirsiniz. Bu yaklaşım, özellikle dışarıdan veri alan uygulamalarda hataları erken yakalar.
Örneğin bir Para sınıfı için eşitlik ve sıralama özel metotlarını tanımlarsanız, para nesnelerini listede sıralayabilir ve karşılaştırabilirsiniz; gösterim metodu hata ayıklarken nesnenin içeriğini okunur biçimde yazdırır. Bu ayrıntılar, kütüphane yazarken kullanıcıların kodunuzu doğal biçimde kullanmasını sağlar.
Tasarım desenleri ve bağımlılık yönetimi
Tasarım desenleri, tekrar eden tasarım problemleri için denenmiş çözüm kalıplarıdır. Örneğin fabrika deseni nesne oluşturmayı bir yere toplar, strateji deseni bir davranışın farklı uygulamalarını değiştirilebilir kılar. Python'da işlevler de nesne olduğu için bazı desenler sınıf gerektirmeden daha sade yazılabilir; bu yüzden deseni ezberlemek yerine çözdüğü problemi anlamak önemlidir.
Bağımlılık yönetimi, bir sınıfın ihtiyaç duyduğu nesneleri kendisi oluşturmak yerine dışarıdan almasıdır. Örneğin e-posta gönderen bir sınıfa gönderici nesnesini kurucuda vermek, testte sahte bir gönderici kullanmayı mümkün kılar. Bu, test edilebilir ve değişime dayanıklı kod yazmanın en pratik yoludur.
Öğrenme yolu ve sık yapılan hatalar
Başlangıçtan ileriye öğrenme sırası şöyle kurulabilir: önce sınıf, nesne ve kapsülleme; sonra kalıtım ve kompozisyon; ardından özel metotlar ve veri sınıfları; en sonda tasarım desenleri, bağımlılık yönetimi ve ileri konular. Her aşamada küçük bir proje, örneğin bir kütüphane ya da sipariş yönetimi uygulaması, kavramları pekiştirir.
Sık hatalar: • Her şeyi sınıfa çevirmek; basit işler için işlev yeterlidir. • Derin kalıtım zincirleri kurmak. • Değiştirilebilir varsayılan değerleri (liste gibi) kurucu parametresi yapmak. • Tek sınıfa çok fazla sorumluluk yüklemek. • Sınıfları test etmeden büyütmek ve refaktör yaparken davranışı doğrulamamak.
Bir sınıfı tasarlarken kendinize sorabileceğiniz kısa bir kontrol listesi: bu sınıfın tek bir sorumluluğu var mı, durumunu dışarıdan kontrolsüz değiştirebiliyor muyuz, bağımlılıklarını dışarıdan alıyor mu, testte sahte bir nesneyle değiştirilebilir mi? Bunlara olumlu yanıt verilemiyorsa tasarım büyümeden önce sadeleştirilmelidir.
Mindset programlarında bu beceriyi nerede çalışırsınız?
Mindset kataloğundaki Python ile Nesne Yönelimli Programlama eğitimi şu modül başlıklarıyla ilerler: Sınıf Temelleri ve Kapsülleme; Kalıtım, Kompozisyon ve Çözüm Sırası; Veri Modeli ve Özel Metotlar; Veri Sınıfları, Tipler ve Doğrulama; Tasarım Desenleri ve Bağımlılık Yönetimi; Metaclass, Kalite ve Refaktör.
İlgili Mindset programı
Python ile Nesne Yönelimli Programlama
Sık sorulan sorular
Python'da OOP öğrenmek için önce neyi bilmek gerekir?
Değişkenler, koşullar, döngüler, işlevler ve temel veri yapıları (liste, sözlük) yeterli bir başlangıçtır. Bu temeller olmadan sınıf yazmak soyut kalır; işlevlerle birkaç küçük program yazdıktan sonra OOP'ye geçmek daha verimlidir.
OOP ile işlevsel programlama arasında seçim yapmak gerekir mi?
Python ikisini de destekler ve gerçek projelerde çoğu zaman karışık kullanılır. Durum ve davranışın birlikte yönetildiği yerlerde sınıf, veri dönüşümü yapan saf işlemlerde ise işlev daha sade sonuç verir. Örneğin bir veri dosyasını okuyup satırları dönüştüren boru hattı işlevlerle sade kalırken, aynı verinin bir de bağlantı, oturum ve önbellek durumunu yönettiği bir servis sınıf olarak daha düzenli olur.
Veri sınıfı ile normal sınıf arasındaki fark nedir?
Veri sınıfı, öncelikle veri taşıyan nesneler için kurucu, gösterim ve karşılaştırma metotlarını otomatik üretir. Normal sınıfta bunları elle yazarsınız. Karmaşık davranış içeren sınıflar için ikisi de kullanılabilir. Veri sınıfı, alanların listesini tek yerde tanımladığı için model katmanında okunabilirlik sağlar; ancak yaşam döngüsü, çok sayıda yardımcı davranış ya da özel başlatma gerektiren nesneler için normal sınıf daha net bir tercihtir.
Metaclass'ı ne zaman öğrenmeliyim?
Başlangıç ve orta düzey için gerekmez. Sınıfların nasıl oluşturulduğunu özelleştirmek isteyen çerçeve ve kütüphane yazarlarının kullandığı ileri bir konudur; temel konular oturduktan sonra ele alınması yeterlidir. Gerçek projelerde metaclass yerine çoğu zaman sınıf dekoratörleri veya kalıtım yeterlidir; metaclass kullanımı koda karmaşıklık ekler, bu nedenle gerçek bir ihtiyaç doğmadan tercih edilmemelidir.