Python’da nesne zihinsel modeli: kimlik, değer, 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, değer ve durum kavramlarını birbirinden ayırabilmeli,
- Bir değişken adının nesnenin kendisi olmadığını açıklayabilmeli,
id(),type(),isve==kullanım amaçlarını ayırabilmeli,- Küçük tamsayı/string gibi nesnelerde uygulama içi önbelleklemenin
issonuçlarını şaşırtabileceğini açıklayabilmeli, - 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. 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.
score = 80ifadesinde score adı, değeri 80 olan bir int nesnesine bağlanır. Daha sonra:
score = 90yazdığımızda “80 nesnesinin içini 90 yapmak” zorunda değiliz; score adı başka bir nesneye yeniden bağlanır.
Python veri modelinde: kimlik, tür ve değer
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,scoresise nesnenin değerini/içeriğini görmemize yardımcı olur.
Değer (value) Python veri modelinin genel terimidir. Durum (state) ise OOP bağlamında, bir nesnenin belirli andaki davranış açısından anlamlı değerlerini anlatmak için kullandığımız tasarım terimidir. Mutable bir nesnenin değeri değiştiğinde çoğu zaman “nesnenin durumu değişti” deriz. Bu iki kavramı birbirine karıştırmadan ilişkilendirin.
id() 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
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
first == second: değer/eşitlik bakımından eşit mi?first is second: aynı nesne mi?first is third: aynı nesne mi?
is 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.
Küçük tamsayı ve string “interning” tuzağı
Öğrenciler genellikle şu deneyi yapar:
a = 5
b = 5
print(a is b)ve bazı ortamlarda True görür. Bunun nedeni Python uygulamasının küçük tamsayıları veya bazı stringleri yeniden kullanabilmesidir (interning/caching). Bu bir uygulama optimizasyonudur; “aynı değerdeki sayılar aynı nesnedir” biçiminde bir dil kuralı değildir.
x = int("1000")
y = int("1000")
print(x == y) # güvenilir değer sorusu
print(x is y) # uygulama ayrıntısına bağlı olabiliris deneylerinden yanlış dil kuralı çıkarmayın
CPython, Pyodide veya başka bir Python uygulamasında önbellekleme davranışı farklı görünebilir. Bu yüzden sayılar ve stringlerde değer karşılaştırması için == kullanın; is sonucunu uygulamanın nesne yeniden kullanım politikasını kanıtlamak için kullanmayın.
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 mutable nesnelerde bu durum zamanla değişebilir.
{"name": "Kalem", "stock": 8}örneğinde stock değeri durumun bir parçasıdır. Stok 8’den 7’ye inerse nesnenin durumu değişir; kimliği ve türü aynı kalabilir.
OOP’de temel soru şudur:
Bu durumun hangi yollarla değişmesine izin veriyoruz?
Davranış neden verinin yanında olmalı?
Program çalışır ama stock = -3 olur. İş kuralı kaybolmuştur.
Fonksiyonu doğrulamayla iyileştirebiliriz:
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. Buna karşılık immutable bir nesnede yeniden bağlama çağıranı değiştirmez:
Alıştırma — Aynı mı, eşit mi?
Ardından c.append(3) ekleyip a, b, c değerlerini tekrar yazdırın.
Alıştırma — Referans diyagramı
first = {"balance": 100}
second = first
third = {"balance": 100}Üç değişken adı ve kaç ayrı sözlük nesnesi olduğunu gösteren bir diyagram çizin. Ardından second["balance"] += 50 sonrası hangi adlar üzerinden 150 görüleceğini açıklayın.
Alıştırma — Geçersiz durumu engelle
if amount > account["balance"]:
raise ValueError("Yetersiz bakiye")Küçük üretim görevi — Prosedürel hesabı incele
account = {
"owner": "Ada",
"balance": 500,
}Para yatırma, para çekme ve bakiye sorgulama fonksiyonlarını yazın. Geçersiz tutarlarda ValueError üretin ve başarısız işlemden sonra sözlüğün değişmediğini doğrulayın.
Çalışır kod teslimi: Normal para çekme, yetersiz bakiye ve negatif tutar senaryolarını çalıştırın; en az üç assert ile bakiyeyi doğrulayı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
- Değişken adı ile nesne arasındaki ilişki nedir?
- Python veri modeline göre nesnenin üç temel özelliği nedir?
- OOP’deki “durum” ile veri modelindeki “değer” nasıl ilişkilidir?
ishangi soruyu sorar?- Küçük tamsayılarda
a is bneden bazenTrueolabilir ve neden buna güvenmemeliyiz? - Aynı mutable nesneye iki referans varsa birinden değişiklik yapılınca diğeri neden yeni durumu görür?
Bu haftadan akılda kalması gerekenler
- Python veri modelinde her nesnenin kimliği, türü ve değeri vardır.
- OOP’de mutable nesnenin zaman içinde değişen anlamlı değerlerini durum olarak yorumlarız.
- Değişken adı nesne değildir; nesneye bağlanır.
==eşitlik,iskimlik sorusudur.- Küçük tamsayı/string önbelleklemesi uygulama ayrıntısıdır; değer karşılaştırmasını
==ile yapın. - 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.