Ek Çalışma — Nesne Durumu İzleme
Nesne durumu izleme çalışmaları
Bu çalışma, Programlama Temelleri’ndeki kod izleme tablosunun nesne dünyasındaki karşılığıdır. Amaç yalnızca çıktıyı bulmak değil, hangi nesnelerin var olduğunu, hangi adların hangi nesnelere bağlandığını ve her nesnenin durumunun satır satır nasıl değiştiğini görünür kılmaktır.
Her soruda önce tabloyu kodu çalıştırmadan doldurun. Tahmininizi tamamladıktan sonra kodu Python’da ve isterseniz Python Tutor üzerinde çalıştırarak kontrol edin. Python Tutor doğrulama aracıdır; tabloyu sizin yerinize dolduran ilk adım değildir.
Kullanacağınız izleme tablosu
Her kritik satırdan sonra aşağıdaki biçimi kullanın. N1, N2 gibi nesne kimlikleri gerçek id() sayıları değildir; çizimde nesneleri ayırt etmek için verdiğiniz sembolik adlardır.
| Satır | Var olan nesneler ve durumları | Ad → nesne bağları | Ne değişti? |
|---|---|---|---|
| 1 | |||
| 2 | |||
| … |
Hafta 6 düzeyi — kimlik, referans ve değiştirilebilirlik
Çalışma 1 — İki ad, tek liste
a = [10, 20]
b = a
b.append(30)
c = [10, 20, 30]Tabloyu 1., 2., 3. ve 4. satırlardan sonra doldurun.
Cevaplamanız gerekenler:
- Kaç ayrı liste nesnesi vardır?
avebaynı nesneyi mi gösterir?a == cvea is csonuçları ne olur?- satırdan sonra
aneden değişmiş görünür?
- satırdan sonra
- satıra kadar tek liste vardır;
avebaynı listeye bağlıdır. 4. satır ikinci, eşit içerikli ama farklı kimlikte bir liste oluşturur. Son durumdaa == cTrue,a is cFalseolur.
Çalışma 2 — Yeniden bağlama nesneyi değiştirmek değildir
x = 100
y = x
x = 101
z = yHer satırdan sonra hangi int değerlerinin erişilebilir olduğunu ve x, y, z adlarının hangi değere bağlı olduğunu yazın.
Cevaplamanız gerekenler:
x = 101satırı 100 değerli nesneyi değiştirir mi?- Son durumda
yvezneden 100 görür? - Bu örnek, liste örneğinden hangi açıdan farklıdır?
x = 101, x adını yeni değere yeniden bağlar. y hâlâ 100 değerine bağlıdır; z = y de 100’e bağlanır. int immutable olduğu için burada liste içeriğini yerinde değiştirmeye benzeyen bir işlem yoktur.
Çalışma 3 — Fonksiyon çağrısında aynı nesne
def etiket_ekle(etiketler):
etiketler.add("oop")
etiketler = {"python"}
yedek_ad = etiketler
etiket_ekle(etiketler)Fonksiyon çağrısı sırasında etiketler parametresinin hangi nesneye bağlandığını da tabloya ekleyin.
Cevaplamanız gerekenler:
- Fonksiyon yeni bir küme kopyası mı oluşturur?
- Çağrıdan sonra
yedek_adüzerinden hangi değer görülür? - Fonksiyon içinde
etiketler = {"oop"}yazılsaydı sonuç neden farklı olurdu?
Parametre adı çağrı sırasında aynı küme nesnesine bağlanır. add() nesneyi yerinde değiştirdiği için dışarıdaki iki ad da yeni durumu görür. Parametreyi yeni bir kümeye yeniden bağlamak ise çağıranın bağını değiştirmez.
Hafta 9 düzeyi — nesne durumu ve kompozisyon
Çalışma 4 — İki sepet, paylaşılan ürün
class Urun:
def __init__(self, ad, fiyat):
self.ad = ad
self.fiyat = fiyat
class Sepet:
def __init__(self):
self.urunler = []
urun = Urun("Kalem", 20)
s1 = Sepet()
s2 = Sepet()
s1.urunler.append(urun)
s2.urunler.append(urun)
urun.fiyat = 25Aşağıdaki nesneleri ayrı satırlarda izleyin: Urun, s1 sepeti, s2 sepeti ve iki sepetin içindeki liste nesneleri.
Cevaplamanız gerekenler:
- Toplam kaç
Urunnesnesi vardır? - İki listenin elemanı aynı
Urunnesnesi midir? - Son satırdan sonra her iki sepetten bakıldığında fiyat neden 25 görünür?
- “Sepete ekleme anındaki fiyat” saklanmak istense tasarımda ne değişmelidir?
Tek bir Urun nesnesi vardır ve iki ayrı sepet listesi aynı ürüne referans tutar. Ürünün durumu değişince iki sepet de aynı nesnenin güncel fiyatını görür. Geçmiş fiyat saklanacaksa sepette ürün referansının yanında o ana ait fiyat değeri/satır nesnesi tutulması düşünülebilir.
Çalışma 5 — Kompozisyon ve delegation
class Adres:
def __init__(self, sehir):
self.sehir = sehir
class Musteri:
def __init__(self, ad, adres):
self.ad = ad
self.adres = adres
def teslimat_sehri(self):
return self.adres.sehir
adres = Adres("Samsun")
musteri = Musteri("Ada", adres)
yedek = adres
adres.sehir = "Ordu"İzleme tablosunda Adres ve Musteri nesnelerini, Musteri.adres alanının hangi nesneye referans verdiğini ve yedek adını gösterin.
Cevaplamanız gerekenler:
- Son durumda
musteri.teslimat_sehri()ne döndürür? musteri.adresileyedekaynı nesneyi mi gösterir?Musteriiçine yalnız"Samsun"string’i kopyalanmış olsaydı davranış nasıl değişirdi?
Musteri.adres ve yedek aynı Adres nesnesine bağlıdır. Bu nesnenin sehir alanı "Ordu" olduğunda delegation üzerinden müşteri de "Ordu" döndürür.
Çalışma 6 — İç koleksiyonu dışarı açmanın etkisi
class NotDefteri:
def __init__(self):
self._notlar = [70, 80]
@property
def notlar(self):
return self._notlar
n = NotDefteri()
dis_liste = n.notlar
dis_liste.append(0)Tabloda NotDefteri nesnesi ile _notlar liste nesnesini ayrı gösterin.
Cevaplamanız gerekenler:
dis_listeyeni bir liste midir?- Son durumda
n.notlarne döndürür? - Bu durum kapsülleme açısından neden risklidir?
- Property
return tuple(self._notlar)döndürse bağlar ve değiştirilebilirlik nasıl değişirdi?
Property aynı mutable listeyi döndürdüğü için dis_liste iç koleksiyona ikinci bir referanstır. Dışarıdan yapılan append() sınıfın davranış metotlarını atlayarak iç durumu değiştirir. Tuple görünümü döndürmek dış kodun iç listeyi bu yoldan yerinde değiştirmesini engeller.
Son çalışma — iki tabloyu karşılaştırın
Çalışma 1 ile Çalışma 4’ü yan yana koyun. Birinde paylaşılan nesne bir liste, diğerinde alan nesnesi olan Urundur. Şu cümleyi kendi sözlerinizle tamamlayın:
Aliasing yalnız listelere özgü değildir; …
Beklenen temel fikir: aynı mutable nesneye birden fazla referans varsa, nesne bir referans üzerinden değiştirildiğinde diğer referanslar da aynı yeni durumu gözlemler.