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,
  • class ile sınıf tanımlayabilmeli,
  • __init__ içinde örnek nitelikleri oluşturabilmeli,
  • self parametresinin 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çı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 örnek oluşturulurken başlangıç durumunu ayarlamak için kullanılan özel metottur.

Note__init__ “nesneyi yoktan yaratan fonksiyon” diye düşünülmemeli

Başlangıç düzeyinde “constructor” sözcüğü yaygın kullanılır; ancak Python veri modelinde nesnenin oluşturulması ile başlatılması ayrıdır. Bu derste ayrıntılı __new__ konusuna girmiyoruz. Pratik olarak __init__’i nesnenin başlangıç durumunu kurduğumuz metot olarak kullanacağız.

__init__ içinde parametrelerin self üzerinden oluşturulan nesnenin alanlarına aktarılması.

self nedir?

Aynı sınıftan iki hesap oluşturalım:

self, metot çağrısının yapıldığı o anki nesneye erişmemizi sağlar. first üzerinden çağrılan metotta selffirst nesnesidir; second üzerinden çağrıda selfsecond nesnesidir.

Metot çağrısında self değerinin çağrıyı alan nesne olması ve metodun bu nesnenin durumunu değiştirmesi.

Davranışı sınıfa eklemek

account.deposit(50) çağrısını zihinsel olarak şu biçimde düşünebilirsiniz:

BankAccount.deposit(account, 50)

Normal kullanımda ilk biçimi tercih ederiz; ikinci biçim self’in nereden geldiğini anlamak için yararlıdır.

Metot yalnızca “fonksiyon sınıf içinde” değildir

Teknik olarak örnek metodu sınıf içinde tanımlanan ve nesne üzerinden bağlanan bir fonksiyondur. Tasarım açısından ise daha önemli bir fikir vardır:

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.

Aynı sınıftan oluşturulan iki nesnenin birbirinden bağımsız durum taşıması.

Sınıf niteliği ile örnek niteliği aynı şey değildir

self.value gibi __init__ içinde oluşturulan nitelikler çoğunlukla örnek niteliğidir (instance attribute). Her nesne kendi değerini taşır.

Buna karşılık sınıf gövdesinde tanımlanan nitelik sınıf tarafından paylaşılır:

name her öğrenci nesnesine özgüdür. school ise sınıfta tanımlanmıştır ve örnekler aynı sınıf niteliğini görebilir.

Sınıf niteliğinin nesneler arasında paylaşılması ve örnek niteliklerinin her nesnede farklı olabilmesi.

Bu fark özellikle değiştirilebilir nesnelerde önemlidir. Aşağıdaki kodu çalıştırmadan önce sonucu tahmin edin:

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 listeyi __init__ içinde oluşturmalıyız:

class Team:
    def __init__(self, name):
        self.name = name
        self.members = []
WarningMutable sınıf niteliğine dikkat

Sınıf niteliği gerçekten bütün örneklerce paylaşılacak veri için anlamlı olabilir. Ancak her nesnenin kendi listesi, sözlüğü veya kümesi olması gerekiyorsa bu mutable nesneyi sınıf gövdesinde değil, __init__ içinde örnek niteliği olarak oluşturun.

Sorumluluğu doğru yere koymak

Şu iki tasarımı karşılaştırın:

# 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

Aşağıdaki sınıfta hata var:

Lamp().turn_on() çağrısında ne olur? Metot tanımındaki eksikliği düzeltin ve tekrar deneyin.

Alıştırma — İki nesnenin durumunu izle

Çalıştırmadan önce çıktıyı tahmin edin. Sonra her çağrıdan sonra iki nesnenin durumunu tablo hâlinde yazın.

Alıştırma — Paylaşılan liste hatasını düzelt

Aşağıdaki tasarımda iki sepetin ürünleri yanlışlıkla ortak listeyi kullanıyor:

Her sepetin kendi items listesine sahip olması için sınıfı düzeltin. Değiştirilebilir listenin neden __init__ içinde oluşturulması gerektiğini bir cümleyle açıklayın.

Küçük üretim görevi — Book sınıfı

Bir Book sınıfı oluşturun:

  • title
  • author
  • is_borrowed

niteliklerine sahip olsun. Başlangıçta is_borrowed = False olsun.

İki metot ekleyin:

  • borrow() → kitabı ödünç alınmış yapar,
  • return_book() → kitabı geri verilmiş yapar.

İ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.

Kendinizi kontrol edin

  1. Sınıf ile nesne arasındaki fark nedir?
  2. self hangi nesneyi temsil eder?
  3. __init__ ne zaman çalışır ve temel amacı nedir?
  4. Aynı sınıftan iki nesnenin nitelikleri neden bağımsız olabilir?
  5. Sınıf niteliği ile örnek niteliği arasındaki fark nedir?
  6. Mutable bir listeyi sınıf gövdesinde tanımlamak hangi durumda sorun yaratabilir?
  7. Bir davranışı metoda dönüştürmek yalnızca kod organizasyonu mudur, yoksa sorumluluk kararı da mıdır?

Bu haftadan akılda kalması gerekenler

  • Sınıf bir tür/şablon 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.
  • Her nesnenin kendi mutable koleksiyonu gerekiyorsa koleksiyonu __init__ içinde oluşturun.
  • Örnek metotları nesnenin davranışlarını ifade eder.
  • İyi OOP tasarımında soru “hangi sınıfa hangi kodu koyarım?” değil, “bu davranış kimin sorumluluğu?”dur.
Back to top