Ek: Nesne durumunu izleme

Nesne durumunu izleme çalışmaları

Programlama Temelleri’nde kodu satır satır izleyip değişkenlerin değerini bir tabloya yazmıştınız. Bu sayfada aynı yöntemi nesnelere uyguluyorsunuz. Bu kez yalnız çıktıyı bulmakla kalmaz, hangi nesnelerin var olduğunu, hangi adın hangi nesneye bağlı olduğunu ve her nesnenin durumunun satır satır nasıl değiştiğini tabloda adım adım izlersiniz.

ImportantÖnce tablo, sonra araç

Her soruda önce tabloyu kodu çalıştırmadan doldurun. Tahmininiz bitince kodu Python’da, isterseniz Python Tutor sitesinde de çalıştırıp kontrol edin. Python Tutor tahmininizi kontrol etmek içindir. Tabloyu sizin yerinize doldurmasın diye onu en başta açmayın.

Kullanacağınız izleme tablosu

Her önemli satırdan sonra tabloya aşağıdaki biçimde bir satır ekleyin. N1, N2 gibi nesne kimlikleri, Python’ın id() ile verdiği gerçek sayılar değildir. Çizimde nesneleri birbirinden ayırmak için sizin koyduğunuz etiketlerdir.

Satır Var olan nesneler ve durumları Ad → nesne bağları Ne değişti?
1
2
…

6. hafta: 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?
  4. Üçüncü satırdan sonra a neden değişmiş görünür?

Üçüncü satıra kadar tek liste vardır; a ve b aynı listeye bağlıdır. Dördüncü satır, içeriği aynı ama kimliği farklı ikinci bir liste oluşturur. Son durumda a == c True, a is c False olur.

Çalışma 2: Adı yeniden bağlamak nesneyi değiştirmez

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

Her satırdan sonra hangi int değerlerine ulaşılabildiğini 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’e bağlıdır?
  3. Bu örneğin liste örneğinden farkı nedir?

x = 101, x adını yeni bir değere bağlar. y hâlâ 100’e bağlıdır; z = y satırıyla z de 100’e bağlanır. int değiştirilemez (immutable) olduğu için burada, listedeki append() gibi nesneyi yerinde değiştiren 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 yazdırılsa ne görülür?
  3. Fonksiyon içinde etiketler = {"oop"} yazılsaydı sonuç neden farklı olurdu?

Çağrı sırasında parametre adı da aynı küme nesnesine bağlanır. add() nesneyi yerinde değiştirdiği için dışarıdaki iki ad da değişmiş kümeyi gösterir. Parametreyi yeni bir kümeye bağlamak ise yalnız fonksiyonun içindeki adı etkiler; çağıran koddaki adlar eski kümeye bağlı kalır.


9. hafta: 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. Ürünün sepete eklendiği andaki fiyatı saklamak isteseydiniz tasarımda neyi değiştirmeniz gerekirdi?

Tek bir Urun nesnesi vardır ve iki ayrı sepet listesi de bu ü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ı saklamak için sepette ürün referansının yanına o anki fiyatı yazabilir ya da ürünü ve fiyatı birlikte tutan bir satır nesnesi kullanabilirsiniz.

Ç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 niteliğinin 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 nesnesi bir Adres yerine yalnız "Samsun" string’ini tutsaydı sonuç nasıl değişirdi?

Musteri.adres ve yedek aynı Adres nesnesine bağlıdır. Bu nesnenin sehir niteliği "Ordu" olunca teslimat_sehri() de "Ordu" döndürür, çünkü metot işi adres nesnesine devreder (delegation).

Çalışma 6: İç listeyi dışarıya vermek

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 içinde return tuple(self._notlar) yazılsaydı dis_liste neye bağlanırdı, onu değiştirebilir miydiniz?

Property iç listenin kendisini döndürdüğü için dis_liste aynı listeye ikinci bir referanstır. Dışarıdan çağrılan append(), sınıfın metotlarından geçmeden iç durumu değiştirir. Property bir tuple kopyası döndürseydi dış kod iç listeyi bu yoldan yerinde değiştiremezdi.

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, ötekinde bir Urun nesnesidir. Şu cümleyi kendi sözlerinizle tamamlayın:

Aliasing yalnız listelere özgü değildir; …

Varmanız beklenen fikir: Aynı mutable nesneye birden çok referans varsa, nesneyi bunlardan biriyle değiştirdiğinizde değişiklik ötekilerden de görünür.

Back to top