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.

ImportantÖnce tablo, sonra araç

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:

  1. Kaç ayrı liste nesnesi vardır?
  2. a ve b aynı nesneyi mi gösterir?
  3. a == c ve a is c sonuçları ne olur?
    1. satırdan sonra a neden değişmiş görünür?
  1. satıra kadar tek liste vardır; a ve b aynı listeye bağlıdır. 4. satır ikinci, eşit içerikli ama farklı kimlikte bir liste oluşturur. Son durumda a == c True, a is c False olur.

Çalışma 2 — Yeniden bağlama nesneyi değiştirmek değildir

x = 100
y = x
x = 101
z = y

Her 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:

  1. x = 101 satırı 100 değerli nesneyi değiştirir mi?
  2. Son durumda y ve z neden 100 görür?
  3. 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:

  1. Fonksiyon yeni bir küme kopyası mı oluşturur?
  2. Çağrıdan sonra yedek_ad üzerinden hangi değer görülür?
  3. 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 = 25

Aşağıdaki nesneleri ayrı satırlarda izleyin: Urun, s1 sepeti, s2 sepeti ve iki sepetin içindeki liste nesneleri.

Cevaplamanız gerekenler:

  1. Toplam kaç Urun nesnesi vardır?
  2. İki listenin elemanı aynı Urun nesnesi midir?
  3. Son satırdan sonra her iki sepetten bakıldığında fiyat neden 25 görünür?
  4. “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:

  1. Son durumda musteri.teslimat_sehri() ne döndürür?
  2. musteri.adres ile yedek aynı nesneyi mi gösterir?
  3. Musteri iç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:

  1. dis_liste yeni bir liste midir?
  2. Son durumda n.notlar ne döndürür?
  3. Bu durum kapsülleme açısından neden risklidir?
  4. 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.

Back to top