Sınıf, nesne, self, __init__ ve metotlar
Artık kendi nesne türlerimizi tanımlayabiliriz. Bir sınıf (class), belirli türde nesnelerin hangi duruma ve davranışlara sahip olacağını tanımlar. Sınıftan oluşturulan her örnek (instance) kendi durumunu taşır.
Bu hafta neleri yapabilmelisiniz?
- Sınıf ile nesne/örnek ayrımını açıklayabilmeli,
classile sınıf tanımlayabilmeli,__init__içinde örnek nitelikleri oluşturabilmeli,selfparametresinin hangi nesneyi temsil ettiğini açıklayabilmeli,- Örnek metodu yazıp çağırabilmeli,
- Durum değişimini metot üzerinden gerçekleştirebilmeli,
- Aynı sınıftan iki nesnenin bağımsız durum taşıdığını gösterebilmeli,
- Sınıf niteliği ile örnek niteliğinin farkını açıklayabilmeli,
- Örnek niteliğinin sınıf niteliğini gölgeleyebileceğini fark edebilmeli,
- Python’da yazım hatasının yanlışlıkla yeni nitelik oluşturabileceğini açıklayabilmelisiniz.
İlk sınıfımız
BankAccount sınıftır; account ise bu sınıftan oluşturulmuş bir nesneye referanstır. __init__, yeni örneğin başlangıç durumunu kurar.
__init__ “nesneyi yoktan yaratan fonksiyon” değildir
Python veri modelinde nesnenin oluşturulması ile başlatılması ayrıdır. Bu derste __new__ ayrıntısına girmiyoruz; pratik olarak __init__’i başlangıç durumunu kurduğumuz metot olarak kullanacağız.
self nedir?
self, metot çağrısının yapıldığı o anki nesneye erişmemizi sağlar. first üzerinden çağrılan metotta self → first; second üzerinden çağrıda self → second nesnesidir.
Davranışı sınıfa eklemek
account.deposit(50) çağrısını zihinsel olarak BankAccount.deposit(account, 50) biçiminde düşünebilirsiniz. Normal kullanım ilk biçimdir; ikincisi self’in nereden geldiğini anlamaya yardım eder.
Metot yalnızca “sınıf içindeki fonksiyon” değildir
Tasarım açısından daha önemli fikir şudur:
Metot, nesnenin sorumluluğuna ait davranışı ifade eder.
deposit() davranışının BankAccount içinde olması, bakiye değişikliğinin hesap nesnesinin sorumluluğunda olduğunu söyler.
Aynı sınıftan bağımsız nesneler
Her nesne kendi value durumunu taşır.
Sınıf niteliği ile örnek niteliği aynı şey değildir
name örnek niteliğidir. school sınıfta tanımlanmıştır ve örnekler, kendilerinde aynı adlı bir nitelik yoksa sınıftaki değeri görür.
Nitelik gölgeleme (shadowing)
Şu atama sınıf niteliğini değiştirmez:
ada.school = ... yalnızca ada nesnesinde aynı adlı bir örnek niteliği oluşturur; bu nitelik sınıftaki school değerini o nesne için gölgeler. Student.school ve ece.school değişmez. Sınıf düzeyindeki değeri gerçekten değiştirmek istiyorsanız niyeti açıkça Student.school = ... ile ifade edin.
Paylaşılan mutable sınıf niteliği
members sınıf niteliği olduğu için iki nesne de aynı listeyi görür. Her takımın bağımsız üye listesine sahip olmasını istiyorsak:
class Team:
def __init__(self, name):
self.name = name
self.members = []Bütün örneklerce gerçekten paylaşılacak veri için sınıf niteliği anlamlı olabilir. Her nesnenin kendi listesi, sözlüğü veya kümesi gerekiyorsa mutable nesneyi __init__ içinde oluşturun.
Yazım hatası bazen sessizce yeni nitelik oluşturur
C gibi statik yapısı daha katı dillerden geçerken şaşırtıcı bir nokta şudur: Python’da çoğu normal sınıf örneğine çalışma sırasında yeni nitelik eklenebilir.
class Account:
def __init__(self):
self.balance = 100
def reset(self):
self.blance = 0 # balance yerine yanlışlıkla blanceself.blance = 0 satırı çoğu durumda hemen hata vermez; yanlış adla yeni nitelik oluşturur. Daha sonra balance hâlâ 100 olduğu için hata mantıksal olarak ortaya çıkar.
Editörün tamamlama/uyarı özelliklerinden yararlanın ve sınıfın durumunu tek tek farklı yerlerde doğaçlama oluşturmamaya çalışın. __init__ içinde beklenen örnek niteliklerini açıkça kurmak bu hataları azaltır.
Kavram radarı: @classmethod ve @staticmethod
Bu hafta yazmanız gereken temel metot türü örnek metodudur ve ilk parametresi self olur. İnternette iki dekoratöre sık rastlayacaksınız:
class User:
@classmethod
def from_text(cls, text):
...
@staticmethod
def is_valid_name(name):
...@classmethodilk parametre olarak örnek yerine sınıfı (cls) alır; alternatif oluşturucu gibi sınıf düzeyindeki davranışlarda kullanılabilir.@staticmethodotomatikselfveyaclsalmaz; sınıfın ad alanında duran, ancak örnek durumuna ihtiyaç duymayan yardımcı davranış için kullanılabilir.
Bu iki mekanizma bu haftanın üretim beklentisi değildir. Öncelik, örnek durumu kullanan davranışta normal instance method yazmayı doğru öğrenmektir.
Sorumluluğu doğru yere koymak
# A: dışarıdan doğrudan güncelleme
account.balance -= 100# B: davranış üzerinden güncelleme
account.withdraw(100)İkinci yaklaşım “para çekmenin kuralları hesabın sorumluluğundadır” dememizi sağlar. Gelecek hafta withdraw içinde geçerli durum kurallarını koruyacağız.
Alıştırma — Sınıfı tamamla
self.price *= (1 - rate)Alıştırma — self hatasını bul
Lamp().turn_on() çağrısında ne olur? Metot tanımındaki eksikliği düzeltin.
Alıştırma — Gölgelemeyi gözlemle
Bir Student sınıfında school sınıf niteliği oluşturun. İki öğrenci üretin; yalnızca ilk öğrenciye student.school = "X" atayın. Üç değeri (first.school, second.school, Student.school) yazdırıp sonucu açıklayın.
Küçük üretim görevi — Book sınıfı
Bir Book sınıfı oluşturun:
titleauthoris_borrowed
Başlangıçta is_borrowed = False olsun. borrow() ve return_book() metotlarını ekleyin. İki ayrı kitap nesnesi oluşturun ve birini ödünç almanın diğerini değiştirmediğini gösterin.
Şimdilik aynı kitabı iki kez ödünç alma gibi geçersiz durumları engellemiyoruz. Gelecek hafta tam olarak bunu yapacağız.
Çalışır kod teslimi: En az iki Book nesnesi üretin; borrow() ve return_book() çağrıları sonrası durumları assert ile kontrol edin. Ayrıca sınıf/örnek niteliği gölgelemesini gösteren en az bir kısa deney ekleyin.
Kendinizi kontrol edin
- Sınıf ile nesne arasındaki fark nedir?
selfhangi nesneyi temsil eder?__init__temel olarak ne yapar?- Sınıf niteliği ile örnek niteliği arasındaki fark nedir?
ada.school = "X"nedenStudent.schooldeğerini değiştirmez?- Mutable bir listeyi sınıf gövdesinde tanımlamak hangi durumda sorun yaratabilir?
self.blanceyazım hatası neden hemen hata vermeyebilir?classmethodilestaticmethodhangi genel amaçları ifade eder?
Bu haftadan akılda kalması gerekenler
- Sınıf bir tür tanımı; nesne o sınıfın çalışma anındaki örneğidir.
self, çağrının hedefindeki nesneye erişim sağlar.__init__başlangıç durumunu kurar.- Örnek nitelikleri nesneye özgü durum taşır; sınıf nitelikleri sınıf düzeyinde paylaşılabilir.
- Örnek üzerinde aynı adlı nitelik oluşturmak sınıf niteliğini gölgeleyebilir.
- Her nesnenin kendi mutable koleksiyonu gerekiyorsa koleksiyonu
__init__içinde oluşturun. - Python’ın dinamik nitelikleri esnektir; yazım hatalarını da sessizleştirebilir.
- İyi OOP tasarımında temel soru “bu davranış kimin sorumluluğu?”dur.