Python’da nesne zihinsel modeli: kimlik, durum ve referans

Bu haftadan itibaren dersin ana konusu nesne tabanlı programlamadır. Ancak hemen class sözdizimine atlamayacağız. Önce Python’da bir nesnenin ne olduğunu, değişken adlarının nesnelerle nasıl ilişki kurduğunu ve aynı nesnenin birden fazla yerden görülebilmesinin ne anlama geldiğini anlamamız gerekir.

Bu hafta neleri yapabilmelisiniz?

  • nesne, referans, kimlik, tür ve durum kavramlarını birbirinden ayırabilmeli,
  • bir değişken adının nesnenin kendisi olmadığını açıklayabilmeli,
  • id(), type(), is ve == kullanım amaçlarını ayırabilmeli,
  • değiştirilebilir nesnelerde ortak referansın etkisini tahmin edebilmeli,
  • fonksiyon parametrelerinin nesnelere erişim sağladığını gözlemleyebilmeli,
  • bir problemde “veri” ile “davranış”ın neden birlikte düşünülebileceğini açıklayabilmelisiniz.

“Değişken kutudur” modeli neden yetersiz kalır?

Başlangıç programlamasında değişkeni bir kutu gibi düşünmek işe yarayabilir: kutunun içinde bir değer varmış gibi. Python’da nesne ilişkilerini anlamaya başladığımızda daha doğru bir model gerekir:

Değişken adı, bir nesneye bağlanır.

Örneğin:

score = 80

ifadesinde score adı, değeri 80 olan bir int nesnesine bağlanır. Daha sonra:

score = 90

yazdığımızda “80 nesnesinin içini 90 yapmak” zorunda değiliz; score adı başka bir nesneye yeniden bağlanır.

Python veri modelinde nesnenin üç temel özelliği

Python dil başvurusunda her nesnenin kimliği (identity), türü (type) ve değeri (value) olduğu belirtilir. Tür, nesnenin desteklediği işlemleri ve değerinin değişip değişemeyeceği gibi özellikleri belirler.

Burada:

  • type(scores) nesnenin türünü,
  • id(scores) çalışma süresi boyunca o nesneyi ayırt eden kimlik değerini,
  • scores ise nesnenin o andaki içeriğini görmemize yardımcı olur.
Noteid() değerini bellek adresi diye ezberlemeyin

Bazı Python uygulamalarında id() ile bellek adresi arasında yakın ilişki olabilir; ancak dil düzeyinde güvenmemiz gereken sözleşme bu değildir. Biz id() değerini yalnızca iki referansın aynı nesneyi gösterip göstermediğini gözlemlemek için kullanacağız. Bu amaç için doğrudan is daha okunaklıdır.

Aynı nesneye iki referans

Aşağıdaki kodu çalıştırmadan önce sonucu tahmin edin:

product ve selected iki farklı sözlük değildir. Aynı sözlük nesnesine iki farklı ad üzerinden erişiyoruz.

Kimlik ve eşitlik aynı soru değildir

Burada:

  • first == second: içerik/değer bakımından eşit mi?
  • first is second: aynı nesne mi?
  • first is third: aynı nesne mi?

sorularını sorar.

Python’da eşit içerikli iki ayrı nesne ile aynı nesneye bağlanan iki değişkenin == ve is sonuçlarıyla karşılaştırılması.
Importantis değer karşılaştırma operatörü değildir

Sayı veya string değerlerini karşılaştırmak için genel olarak == kullanın. is, nesne kimliği sorusudur ve özellikle None kontrolünde (value is None) yaygın biçimde kullanılır.

Nesnenin durumu

OOP bağlamında bir nesnenin belirli bir andaki, davranış açısından anlamlı değerlerini onun durumu (state) olarak düşünürüz. Özellikle değiştirilebilir (mutable) nesnelerde bu durum zamanla değişebilir.

Sözlük örneğinde:

{"name": "Kalem", "stock": 8}

stok değeri durumun bir parçasıdır. Bir işlem stok değerini 8’den 7’ye indirirse nesnenin durumu değişmiştir; nesnenin kimliği ve türü ise aynı kalabilir.

OOP’de temel soru şudur:

Bu durumun hangi yollarla değişmesine izin veriyoruz?

Eğer herkes stock değerini istediği gibi değiştirebiliyorsa negatif stok gibi geçersiz durumlar kolayca oluşabilir.

Davranış neden verinin yanında olmalı?

Şu prosedürel yaklaşımı düşünün:

Program çalışır ama stock = -3 olur. İş kuralı kaybolmuştur.

Fonksiyonu doğrulamayla iyileştirebiliriz:

Bu daha güvenlidir. Fakat sistem büyüdükçe product sözlüğünün hangi anahtarlara sahip olması gerektiği ve hangi fonksiyonların onu değiştirebildiği dağınık hâle gelebilir. Sınıf, durum ve davranışa ortak bir ad ve sınır vermemizi sağlar.

Fonksiyon parametresi nesneyi kopyalamaz

Fonksiyon, aynı küme nesnesine erişir. Bu yüzden değişiklik çağıranın gördüğü nesnede de vardır.

Buna karşılık immutable bir nesnede yeniden bağlama çağıranı değiştirmez:

Burada fonksiyon içindeki number adı yeni int nesnesine bağlanır; dışarıdaki value aynı şekilde kalır.

Alıştırma — Aynı mı, eşit mi?

Çalıştırmadan önce dört satırın her biri için True/False tahmin edin:

Ardından c.append(3) ekleyip a, b, c değerlerini tekrar yazdırın.

Alıştırma — Referans diyagramı

Aşağıdaki kod için kâğıda basit bir referans diyagramı çizin:

first = {"balance": 100}
second = first
third = {"balance": 100}

Üç değişken adı ve kaç ayrı sözlük nesnesi olduğunu gösterin. Ardından:

second["balance"] += 50

satırından sonra hangi değişkenler üzerinden 150 görüleceğini açıklayın.

Alıştırma — Geçersiz durumu engelle

Aşağıdaki fonksiyonu, bakiyenin negatif olmasına izin vermeyecek biçimde tamamlayın:

if amount > account["balance"]:
    raise ValueError("Yetersiz bakiye")

Küçük üretim görevi — Prosedürel hesabı incele

Aşağıdaki veri modelini temel alın:

account = {
    "owner": "Ada",
    "balance": 500,
}

Şu davranışlar için fonksiyonlar yazın:

  • para yatırma,
  • para çekme,
  • bakiye sorgulama.

Her davranışta geçersiz durumları düşünün. Sonunda şu soruyu cevaplayın:

Bu üç fonksiyonu ve hesabın verisini tek bir kavram altında toplamak istersek ne kazanırız?

Bu sorunun cevabı gelecek haftanın class Account tasarımına geçişidir.

Kendinizi kontrol edin

  1. Değişken adı ile nesne arasındaki ilişki nedir?
  2. Python veri modeline göre her nesnenin hangi üç temel özelliği vardır?
  3. is hangi soruyu sorar?
  4. id() değerini neden doğrudan “bellek adresi” diye yorumlamıyoruz?
  5. Aynı listeye iki referans varsa birinden append() yapılınca diğeri neden değişmiş görünür?
  6. Immutable int üzerinde fonksiyon içindeki yeniden bağlama dışarıyı neden değiştirmez?
  7. Durumun geçerliliğini yalnızca dış fonksiyonlara bırakmanın sakıncası nedir?

Bu haftadan akılda kalması gerekenler

  • Python veri modelinde her nesnenin kimliği, türü ve değeri vardır.
  • OOP bağlamında mutable bir nesnenin zaman içinde değişebilen anlamlı değerlerini onun durumu olarak düşünürüz.
  • Değişken adı nesne değildir; nesneye bağlanır.
  • == eşitlik, is kimlik sorusudur.
  • Aynı mutable nesneye birden fazla referans olabilir.
  • OOP’nin motivasyonlarından biri, durumu ve onu değiştiren kurallı davranışları aynı sorumluluk sınırında toplamaktır.
Back to top